//  Copyright (c) Microsoft Corporation.  All rights reserved.

namespace Microsoft.VisualStudio.TestTools.TestCaseMigrator
{

    /// <summary>
    /// Base class for All wizard Parts
    /// </summary>
    internal abstract class BaseWizardPart : NotifyPropertyChange, IWizardPart
    {
        #region Fields

        /// <summary>
        /// Member variables needed for data binding
        /// </summary>
        private string m_header;
        private string m_description;
        private bool m_canBack;
        private bool m_canNext;
        private bool m_canFinish;
        protected bool m_canShow;
        private bool m_isActiveWizardPart;

        protected WizardPartPrerequisite m_prerequisite;

        // WizardInfo
        protected WizardInfo m_wizardInfo;

        #endregion

        #region Constants

        // Needed for the notification of CanFinish
        public const string CanFinishPropertyName = "CanFinish";
        public const string HeaderPropertyName = "Header";
        public const string DescriptionPropertyName = "Description";
        public const string CanBackPropertyName = "CanBack";
        public const string CanNextPropertyName = "CanNext";

        #endregion

        #region Constructor

        /// <summary>
        /// Base Constructor to initialize Error Info
        /// </summary>
        public BaseWizardPart()
        {
            // Initializing the ErrorArgs
            ErrorArgs = new MessageEventArgs();
            ErrorArgs.Category = MessageCategory.Error;
            ErrorArgs.CancelButtonLabel = Resources.CloseButtonLabel;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Header of a Wizard Page
        /// </summary>
        public string Header
        {
            get
            {
                return m_header;
            }
            protected set
            {
                m_header = value;
                NotifyPropertyChanged(HeaderPropertyName);
            }
        }

        /// <summary>
        /// Description of the Wizard page
        /// </summary>
        public string Description
        {
            get
            {
                return m_description;
            }
            protected set
            {
                m_description = value;
                NotifyPropertyChanged(DescriptionPropertyName);
            }
        }

        /// <summary>
        /// ErrorArgs - It is updated whenever any error occurs in the wizard part.
        /// It can be leveraged by the Wizard to show Wizard Part Error
        /// </summary>
        public MessageEventArgs ErrorArgs
        {
            get;
            protected set;
        }

        /// <summary>
        /// Is Back button of Wizard Enabled
        /// </summary>
        public bool CanBack
        {
            get
            {
                return m_canBack;
            }
            protected set
            {
                m_canBack = value;
                NotifyPropertyChanged(CanBackPropertyName);
            }
        }

        /// <summary>
        /// Is Next Button of Wizard enabled
        /// </summary>
        public bool CanNext
        {
            get
            {
                return m_canNext;
            }
            protected set
            {
                m_canNext = value;
                NotifyPropertyChanged(CanNextPropertyName);
            }
        }

        /// <summary>
        /// Is Finish Button of wizard Enabled?
        /// </summary>
        public bool CanFinish
        {
            get
            {
                return m_canFinish;
            }
            protected set
            {
                m_canFinish = value;
                NotifyPropertyChanged(CanFinishPropertyName);
            }
        }

        /// <summary>
        /// Whether we can show this WizardPage
        /// </summary>
        public bool CanShow
        {
            get
            {
                return m_canShow;
            }
            set
            {
                m_canShow = value;
                NotifyPropertyChanged("CanShow");
            }
        }

        /// <summary>
        /// Checks that we can initialize Wizard Part or not.
        /// </summary>
        public bool CanInitialize
        {
            get
            {
                if (m_wizardInfo == null)
                {
                    return false;
                }

                CanInitializeWizardPage(m_wizardInfo);
                NotifyPropertyChanged("CanShow");
                return CanShow;
            }
        }

        /// <summary>
        /// The State of Wizard Page. It is unique for each Wizard Page.
        /// </summary>
        public WizardPage WizardPage
        {
            get;
            protected set;
        }

        /// <summary>
        /// Is this Wizard Page in active and currently in process?
        /// </summary>
        public bool IsActiveWizardPart
        {
            get
            {
                return m_isActiveWizardPart;
            }
            set
            {
                m_isActiveWizardPart = value;
                NotifyPropertyChanged("IsActiveWizardPart");
            }
        }

        #endregion

        #region abstract and virtual methods

        /// <summary>
        /// Initializes the Wizard Part and Send Notifications
        /// </summary>
        /// <param name="info"></param>
        public virtual void Initialize(WizardInfo info)
        {
            if (!CanInitializeWizardPage(info))
            {
                return;
            }


            if (IsInitializationRequired(info))
            {
                m_wizardInfo = info;

                if (m_prerequisite == null)
                {
                    m_prerequisite = new WizardPartPrerequisite(info);
                }

                try
                {
                    Reset();
                }
                catch (TestCaseMigratorException ex)
                {
                    ErrorArgs = ex.Args;
                    CanShow = false;
                    m_wizardInfo = null;
                }
            }
            m_prerequisite.Save();
            FireStateNotifications();
        }


        /// <summary>
        /// Abstract Method : Resets the wizard part
        /// </summary>
        public abstract void Reset();


        /// <summary>
        /// Abstract Method : Updates the Wizard info with the current Wizard State.
        /// </summary>
        /// <returns>Whether Updation was successful?</returns>
        public abstract bool UpdateWizardPart();


        /// <summary>
        /// Used by Initialize to check whether Initialization is required or not
        /// </summary>
        /// <param name="state"></param>
        /// <returns></returns>
        protected virtual bool IsInitializationRequired(WizardInfo state)
        {
            return (m_wizardInfo == null);
        }

        /// <summary>
        /// Validates whether the Wizard part State is Valid or not
        /// </summary>
        /// <returns></returns>
        protected abstract bool ValidatePartState();

        protected virtual bool IsUpdationRequired()
        {
            return true;
        }

        protected abstract bool CanInitializeWizardPage(WizardInfo info);

        /// <summary>
        /// Send The Notifications for Data Binding
        /// </summary>
        public virtual void FireStateNotifications()
        {
            NotifyPropertyChanged(HeaderPropertyName);
            NotifyPropertyChanged(DescriptionPropertyName);
            NotifyPropertyChanged(CanBackPropertyName);
            NotifyPropertyChanged(CanNextPropertyName);
            NotifyPropertyChanged(CanFinishPropertyName);
            NotifyPropertyChanged("CanShow");
        }

        #endregion
    }
}
