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

namespace SimplifyXR
{

    public class ManualObjectAnchorAlignment : MonoBehaviour, IObjectAnchorAlignment
{

        public UnityEvent placementStartedEvent = new UnityEvent();
        public UnityEvent placementEndedEvent = new UnityEvent();
        public UnityEvent manipulationStartedEvent = new UnityEvent();
        public UnityEvent manipulationEndedEvent = new UnityEvent();

        public AlignmentState manualAlignmentState;
        public ManualPlacementBehavior placementBehaviorType;

        private IPlacementBehavior placementBehavior;
        private StandardAssetsBoundsControl boundsControl;
        private GameObject anchorObject;

        public UnityEvent placementStarted { get => placementStartedEvent; set => placementStartedEvent = value; }
        public UnityEvent placementEnded { get => placementEndedEvent; set => placementEndedEvent = value; }
        public UnityEvent manipulationStarted { get => manipulationStartedEvent; set => manipulationStartedEvent = value; }
        public UnityEvent manipulationEnded { get => manipulationEndedEvent; set => manipulationEndedEvent = value; }

        public AlignmentState alignmentState => manualAlignmentState;

        public void SetBehavior(ManualPlacementBehavior behavior)
        {
            placementBehaviorType = behavior;
            SetupPlacementBehavior();
        }

        private void SetupPlacementBehavior()
        {
            //currently we only set this on construction, feature improvement could be changing at runtime
            switch (placementBehaviorType)
            {
                case ManualPlacementBehavior.MRTK_TapToPlace:
                    placementBehavior = anchorObject.GetOrAddNewComponent<ManualPlacementMRTK2TapToPlace>();

                    placementBehavior.placementStarted?.AddListener(() => placementStartedEvent?.Invoke());
                    placementBehavior.placementEnded?.AddListener(() => placementEndedEvent?.Invoke());
                    placementBehavior.placementEnded?.AddListener(HandlePlacementStopped);

                    break;
            }
            boundsControl = anchorObject.GetOrAddNewComponent<StandardAssetsBoundsControl>();
            boundsControl.EnableManipulators(false);
        }

        void Awake()
        {
            //default anchor
            anchorObject = gameObject;

            manualAlignmentState = AlignmentState.Placement;
        }

        private void OnDestroy()
        {
            RemovePlacementBehavior(); 
        }
        public void OnDisable()
        {
            placementBehavior.placementStarted.RemoveAllListeners();
            placementBehavior.placementEnded.RemoveAllListeners();
        }
        private void RemovePlacementBehavior()
        {
            placementBehavior.StopPlacement();
            manualAlignmentState = AlignmentState.None;

                switch (placementBehaviorType)
                {
                    case ManualPlacementBehavior.MRTK_TapToPlace:
                        placementBehavior.placementStarted.RemoveAllListeners();
                        placementBehavior.placementEnded.RemoveAllListeners();

                        Destroy(anchorObject.GetComponent<ManualPlacementMRTK2TapToPlace>());
                        break;
                }
            Destroy(boundsControl);
        }

        public void StartAlignment()
        {
            placementBehavior.EnablePlacement(true);

            manualAlignmentState = AlignmentState.Placement;
            placementBehavior.StartPlacement();
        }

        public void ConfirmAlignment()
        {
            manualAlignmentState = AlignmentState.ConfirmedAlignment;
            placementBehavior.EnablePlacement(false);
            boundsControl.EnableManipulators(false);
        }

        public void StopAlignment()
        {
            manualAlignmentState = AlignmentState.None;
            placementBehavior.EnablePlacement(false);
            boundsControl.EnableManipulators(false);
        }

        private void HandlePlacementStopped()
        {
            placementBehavior.EnablePlacement(false);

            manualAlignmentState = AlignmentState.Manipulate;

            boundsControl.EnableManipulators(true);
        }

        public void SetAlignment(Vector3 pos, Vector3 rot, bool useCurrentPose)
        {
            if (!useCurrentPose)
            {
                anchorObject.transform.position = pos;
                //may need to use quat, inspector is set through euler
                anchorObject.transform.eulerAngles = rot;
            }

            placementBehavior.StopPlacement();
        }

        public void SetAnchorObject(GameObject anchor)
        {

        }

    }
}
