using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace SimplifyXR
{
    [System.Serializable]
    public class CustomStartEndOffset
    {
        public int startStepOffset;
        public int endStepOffset;
    }


    public class simpleARInstructionFeatures : BasePanelFeatures, IObserveStepChange
    {
        [Header("Instruction Panel Features")]

        [Tooltip("Toggle to customize the default behaviors of the Standard Instruction Panel.")]
        public bool customizeFeatures = false;
        [Conditional("customizeFeatures", true, ComparisonType.Equals), 
            Tooltip("Enable the back button's default behavior tied to a Step Sequence.")]
        public bool autoBackButton = true;
        [Conditional("customizeFeatures", true, ComparisonType.Equals), 
            Tooltip("Enable the next button's default behavior tied to a Step Sequence.")]
        public bool autoNextButton = true;
        [Conditional("customizeFeatures", true, ComparisonType.Equals), 
            Tooltip("Auto populate the title of the Panel based on the Step Sequence name.")]
        public bool autoPopulateProcedureTitle = true;
        [Conditional("customizeFeatures", true, ComparisonType.Equals), 
            Tooltip("Auto populate the step instruction based on the current step instruction in the Step Sequence.")]
        public bool autoPopulateStepInstruction = true;
        [Conditional("customizeFeatures", true, ComparisonType.Equals), 
            Tooltip("Auto populate the step name based on the current step instruction in the Step Sequence.")]
        public bool autoPopulateStepName = true;
        [Conditional("customizeFeatures", true, ComparisonType.Equals),
             Tooltip("Auto populate the instruction title based on the current step instruction in the Step Sequence.")]
        public bool autoPopulateInstructionTitle = true;
        [Conditional("customizeFeatures", true, ComparisonType.Equals), 
            Tooltip("Auto fill the progress bar based on the current step in the Step Sequence")]
        public bool autoFillProgressBar = true;
        [Conditional("customizeFeatures", true, ComparisonType.Equals),
            Tooltip("Auto fill the step progress text based on the current step in the Step Sequence.")]
        public bool autoFillProgressText = true;
        [Conditional("customizeFeatures", true, ComparisonType.Equals),
           Tooltip("Auto submit a multiple choice selection when progressing to the next step.")]
        public bool autoSubmitMultiChoiceOnNext = true;

#if UNITY_EDITOR
        [Tooltip("Use custom start step and end step for progress range")]
#endif
        public bool UseCustomStartAndEnd;

#if UNITY_EDITOR
        [Conditional("UseCustomStartAndEnd",
            true, ComparisonType.Equals)]
#endif
        //public GetStepSequenceProgress.CustomStartAndEnd customStartAndEnd;
        public CustomStartEndOffset customStartAndEnd;


        private InstructionElementRoot root;
        #region SimpleAR Pro Features

        public string StepToListenFor => "Test";

        public string Project => activeProject;
        private string activeProject = "";
        private Coroutine fillRoutine;

        public int Priority => 0;

        public int currentStepNumber { get; private set; }

        public void StepChange(StepEventArgs args)
        {
            root?.note?.gameObject.SetActive(false);
            root?.multipleChoice?.gameObject.SetActive(false);

            DisableNextProgress(false);

            var stepLoader = new BasicStepLoader();
            stepLoader.LoadStepContent(args.StepName);
            if (autoPopulateStepInstruction) root.instructionText.text = stepLoader.Instruction;
            if (autoPopulateProcedureTitle) root.panelTitle.text = args.ProjectName;
            if (autoPopulateStepName) root.panelTitle.text += " / " + stepLoader.StepTitle;
            if (autoPopulateInstructionTitle) root.panelTitle.text += " / " + stepLoader.Title;

            int stepNumber = StepManager.Instance.GetAvailableSteps().IndexOf(args.StepName);
            int totalSteps = StepManager.Instance.GetAvailableSteps().Count - 2;

            var panelRoot = root.instructionPanel.transform.parent.parent.gameObject;
            panelRoot?.SetActive(false);
            panelRoot?.SetActive(true);

            root.nextButton.interactable = stepNumber != totalSteps;
            root.backButton.interactable = stepNumber != 1;

            if (UseCustomStartAndEnd)
            {
                /*
                int startOffset = StepManager.Instance.GetAvailableSteps().IndexOf(customStartAndEnd.Start.stepName) - 1;
                int endOffset =
                    (StepManager.Instance.GetAvailableSteps().Count - 2) -
                    StepManager.Instance.GetAvailableSteps().IndexOf(customStartAndEnd.End.stepName);
                */
                int startOffset = customStartAndEnd.startStepOffset;
                int endOffset = customStartAndEnd.endStepOffset;

                totalSteps -= startOffset + endOffset;
                stepNumber -= startOffset;
                if (stepNumber < 1 || stepNumber > totalSteps)
                {
                    ResetStepProgress();
                    return;
                }
            }

            currentStepNumber = stepNumber;

            UpdateProgressBar(stepNumber, totalSteps);
        }



        private void UpdateProgressBar(int stepNumber, int totalSteps)
        {
            if (autoFillProgressBar)
            {
                if (fillRoutine != null) StopCoroutine(fillRoutine);
                StartCoroutine(UpdateProgressFill(
                    (float)stepNumber /
                    (float)totalSteps)
                    );
            }

            if (autoFillProgressText) root.progressText.text =
                 stepNumber.ToString() + " of " +
                 totalSteps.ToString();
        }

        private void ResetStepProgress()
        {
            if (autoFillProgressBar) root.progressBarOuter.fillAmount = 0;
            if (autoFillProgressText) root.progressText.text = "";
        }

        public void GoToNextStep()
        {
            if (autoSubmitMultiChoiceOnNext)
            root.multipleChoice.SubmitMultipleChoiceSelection();
           
            StepManager.Instance.GoToNextStep();
        }


        public void GoBackAStep()
        {
            StepManager.Instance.GoBackAStep();
        }


        public void DisplayNote(NoteMessage message)
        {
            root.note.gameObject.SetActive(false);
            root.note.gameObject.SetActive(true);
            root.note.UpdateNote(message);
        }

        public void DisplayMultipleChoice(MultipleChoiceMessage message)
        {
            root.multipleChoice.gameObject.SetActive(false);
            root.multipleChoice.gameObject.SetActive(true);
            root.multipleChoice.UpdateMultipleChoice(message);
        }

        public void AcknowledgeNote(string id)
        {
            if (RequirementsComplete())
                DisableNextProgress(false);
        }

        public void HandleSelection(bool selection)
        {
            if (RequirementsComplete())
                DisableNextProgress(false);
        }

        private bool RequirementsComplete()
        {
            if (root.note.gameObject.activeInHierarchy)
            {
                if (root.acknowledgeButton.gameObject.activeInHierarchy)
                    return false;
            }
            
            if (root.multipleChoice.gameObject.activeInHierarchy)
            {
                if (!root.multipleChoice.RequirementsComplete())
                {
                    return false;
                }
            }

            return true;
        }

        public void HandleDisplay(bool hasRequirements)
        {
            if (hasRequirements)
            {
                DisableNextProgress(hasRequirements);
            }
            else
            {
                if (RequirementsComplete())
                {
                    DisableNextProgress(hasRequirements);
                }
            }
        }

        public void DisableNextProgress(bool disable)
        {
            root.nextButton.interactable = !disable;
        }

        [ContextMenu("Test Note")]
        public void TestNote()
        {
            NoteMessage message = new NoteMessage();
            message.noteType = NoteType.Warning;
            message.requiresAcknowledgement = true;
            DisplayNote(message);
        }


        IEnumerator UpdateProgressFill(float targetFill)
        {
            var startFill = root.progressBarOuter.fillAmount;

            for (float i = 0; i < 0.25f; i += Time.deltaTime)
            {
                root.progressBarOuter.fillAmount = Mathf.Lerp(
                    startFill,
                    targetFill,
                    i / 0.25f);
                yield return null;
            }
            root.progressBarOuter.fillAmount = targetFill;
        }


        public void SetupProject(StepEventArgs args)
        {
            activeProject = args.ProjectName;
            root.note.gameObject.SetActive(false);
            StepManager.Instance.Attach(this);
            ResetStepProgress();
            StepChange(args);
        }


        public new void Awake()
        {
            base.Awake();
            StepManager.Instance.ProjectBegan += SetupProject;
            root = GetComponentInChildren<InstructionElementRoot>();
            if (autoBackButton) root.nextButton.onClick.AddListener(GoToNextStep);
            if (autoNextButton) root.backButton.onClick.AddListener(GoBackAStep);
            root.note.OnNoteAcknowledged.AddListener(AcknowledgeNote);
            root.note.OnNoteDisplayed.AddListener(HandleDisplay);
            
            root.multipleChoice.OnMultipleChoiceDisplayed.AddListener(HandleDisplay);
            root.multipleChoice.OnMultipleChoiceSelected.AddListener(HandleSelection);

        }

        public new void OnDestroy()
        {

            base.OnDestroy();
            StepManager.Instance.Detach(this);
            StepManager.Instance.ProjectBegan -= SetupProject;
            if (autoBackButton) root.backButton.onClick.RemoveAllListeners();
            if (autoNextButton) root.nextButton.onClick.RemoveAllListeners();
            root.note.OnNoteAcknowledged.RemoveAllListeners();
            root.note.OnNoteDisplayed.RemoveAllListeners();

            root.multipleChoice.OnMultipleChoiceDisplayed.RemoveAllListeners();
            root.multipleChoice.OnMultipleChoiceSelected.RemoveAllListeners();
        }
        #endregion


    }
}