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

#if USING_MRTK3
    using Microsoft.MixedReality.Toolkit.SpatialManipulation;
#endif

namespace SimplifyXR{

    public class NavMenuDock : MonoBehaviour
    {

        List<Tuple<NavButton, GameObject>> itemsDocked;
        GameObject activeItemDocked;
        public AnimationCurve dockCurve;
        public float dockTime;

        public void OnEnable()
        {
            if(activeItemDocked) activeItemDocked.SetActive(false);
        }

        public void Awake()
        {
            itemsDocked = new List<Tuple<NavButton,GameObject>>();
        }

        
        

        public void DockItem(NavButton button, GameObject panel)
        {

            itemsDocked.ForEach(e => e.Item2.SetActive(false));

            panel.transform.SetParent(this.transform);

            if(itemsDocked.Find(e => e.Item2 == panel) == null) itemsDocked.Add(
                new Tuple<NavButton, GameObject>(button, panel));
            button.UpdateNavItemPanelAnchoredState(true);       

            panel.SetActive(true);
            activeItemDocked = panel;
            StartCoroutine(RetrievePanel(panel));

#if USING_XRI || USING_MRTK3
            var billboard = panel.GetComponentInChildren<Billboard>();
            if(billboard) billboard.enabled = false;
#endif

#if USING_MRTK3

            UnityAction<float> undockActiveItem = 
                (e) => { UndockActiveItem(panel, button); };
            var om = panel.GetComponentInChildren<ObjectManipulator>();
            om?.IsRaySelected.OnEntered.RemoveAllListeners();
            om?.IsRaySelected.OnEntered.AddListener(undockActiveItem);

            var handMenu = panel.GetComponentInParent<HandConstraintPalmUp>();

            if (handMenu) OrientAnchorByHandedness(
                handMenu.Handedness == Microsoft.MixedReality.Toolkit.Handedness.Left);
#endif

#if USING_MRTK2
            var billboardMRTK2 = 
                panel.GetComponentInChildren<Microsoft.MixedReality.Toolkit.UI.Billboard>();
            if (billboardMRTK2) billboardMRTK2.enabled = false;

             UnityAction<Microsoft.MixedReality.Toolkit.UI.ManipulationEventData> 
                undockActiveMRTK2 =
                (e) => { UndockActiveItem(panel, button); };

            var omMRTK2 = 
                panel.GetComponentInChildren<Microsoft.MixedReality.Toolkit.UI.ObjectManipulator>();
            omMRTK2?.OnManipulationStarted.RemoveAllListeners();
            omMRTK2?.OnManipulationStarted.AddListener(undockActiveMRTK2);
            omMRTK2.enabled = true;


            var handMenuMRTK2 = panel.GetComponentInParent<Microsoft.MixedReality.Toolkit.Utilities.Solvers.HandConstraintPalmUp>();
            if(handMenuMRTK2) OrientAnchorByHandedness(
                 handMenuMRTK2.Handedness ==
                 Microsoft.MixedReality.Toolkit.Utilities.Handedness.Left);
#endif

            var panelElements = panel.GetComponentInChildren<ElementRoot>();
            UnityAction clearAnchorState = () =>
            {
                button.UpdateNavItemPanelAnchoredState(true);
            };

            if(panelElements.closeButton != null)
            {
                panelElements.closeButton.onClick.RemoveListener(clearAnchorState);
                panelElements.closeButton.onClick.AddListener(clearAnchorState);
            }         
        }


        private void OrientAnchorByHandedness(bool leftHand)
        {
            var xPos = leftHand ?
                  Mathf.Abs(this.transform.localPosition.x) :
                  Mathf.Abs(this.transform.localPosition.x) * -1;

            this.transform.localPosition =
                new Vector3(xPos,
                this.transform.localPosition.y,
                this.transform.localPosition.z);
        }

        IEnumerator RetrievePanel(GameObject panel)
        {
            var canvasTrans = panel.GetComponentInChildren<Canvas>()?.transform;

            var startPos = panel.transform.localPosition;
            var startScale = panel.transform.localScale;

           var startCanvasPos = canvasTrans ? canvasTrans.transform.localPosition : Vector3.zero;
           var canvasStartScale = canvasTrans ? canvasTrans.transform.localScale : Vector3.zero;
           var startCanvasRot = canvasTrans ? canvasTrans.transform.rotation : Quaternion.identity;       
         
            for (float i = 0; i < dockTime; i += Time.deltaTime) {

                var dockVal = dockCurve.Evaluate(i / dockTime);

                panel.transform.localPosition = Vector3.Lerp(startPos, Vector3.zero, dockVal);
                panel.transform.localScale = Vector3.Lerp(startScale, new Vector3(1f,1f,1f), dockVal);

                if(canvasTrans) canvasTrans.transform.localPosition = Vector3.Lerp(startCanvasPos, Vector3.zero, dockVal);
                if (canvasTrans) canvasTrans.transform.localScale = Vector3.Lerp(canvasStartScale, new Vector3(1f, 1f, 1f), dockVal);
                if (canvasTrans) canvasTrans.rotation = Quaternion.Lerp(startCanvasRot, this.transform.rotation, dockVal);

                yield return null;
            }

            panel.transform.localPosition = Vector3.zero;
            panel.transform.localScale = new Vector3(1f, 1f, 1f);

            if (canvasTrans) canvasTrans.transform.localPosition = Vector3.zero;
            if (canvasTrans) canvasTrans.transform.localScale = new Vector3(1f, 1f, 1f);
            if (canvasTrans) canvasTrans.rotation = this.transform.rotation;
        }


        private void UndockActiveItem(GameObject panel, NavButton button)
        {

            if (!gameObject.activeInHierarchy) return;

            activeItemDocked = null;
            button.UpdateNavItemPanelAnchoredState(false);

#if USING_XRI || USING_MRTK3

            var billboard = panel.GetComponentInChildren<Billboard>();
            if(billboard) billboard.enabled = true;
#endif
            panel.transform.SetParent(null);

#if USING_MRTK2

            var billboardMRTK2 = panel.GetComponentInChildren<Microsoft.MixedReality.Toolkit.UI.Billboard>();
            if (billboardMRTK2) billboardMRTK2.enabled = true;
            var eventCamera = this.GetComponentInParent<Canvas>().worldCamera;
            var canvas = panel.GetComponentInChildren<Canvas>();
            if (canvas) canvas.worldCamera = eventCamera;
#endif
            itemsDocked.RemoveAll(e =>  e.Item2 == panel);
        }
    }
}

