/*
Copyright 2019 Dr. Thomas Benjamin Senior, Michael Zoeller 

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

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

namespace EyeSkills
{
    public delegate void MicroControllerShutDown();

    public abstract class MicroController : MonoBehaviour
    {
        /// <summary>
        /// Called on startup. When finished, calls the shutdownFunction delegate
        /// </summary>
        /// <returns>The startup.</returns>
        /// <param name="shutdownFunction">Shutdown function.</param>
        //abstract public void Startup(MicroControllerShutDown shutdownFunction);
        abstract public void Startup(EyeSkillsCameraRigEditMode parent);

        /// <summary>
        /// Shutdown this instance from the outside.
        /// </summary>
        abstract public void Shutdown();
    }

    [System.Serializable]
    public class MicroControllerMenuItem
    {
        public string text, audioID;
        public MicroController microController;
    }

    /// <summary>
    /// Eye skills camera rig edit mode. This handles the selection/activation/deactivation of our micro-controllers
    /// </summary>
    public class EyeSkillsCameraRigEditMode : MonoBehaviour
    {
        private EyeSkillsInput esInput;
        protected AudioManager audioManager;
        private bool inEditMode = false;
        private int menuIndex = 0;
        private MicroController mc;

        public GameObject mainSceneController;

        // Our local micro-controllers which we activate/deactivate
        /// <summary>
        /// The micro controllers. The key relates to the audio file we render for the virtual menu
        /// </summary>
        public MicroControllerMenuItem[] microControllers;

        void Start()
        {
            audioManager = AudioManager.instance;
            //esInput = GetComponent<EyeSkillsInput>();
            esInput = EyeSkillsInput.instance;
        }

        private int moveMenuIndexUp(int currentIndex)
        {
            if (currentIndex > 0)
            {
                currentIndex -= 1;
            }
            else
            {
                currentIndex = microControllers.Length - 1;
            }

            return currentIndex;
        }

        private int moveMenuIndexDown(int currentIndex)
        {
            if (currentIndex < microControllers.Length - 1)
            {
                currentIndex += 1;
            }
            else
            {
                currentIndex = 0;
            }

            return currentIndex;
        }

        void EnterEditMode()
        {
            audioManager.Say("EnteringDirectCameraEditMode");
            inEditMode = true;
            // First we need to disable the current controller
            mainSceneController.SetActive(false);
        }

        void LeaveEditMode()
        {
            audioManager.Say("LeavingDirectCameraEditMode");
            inEditMode = false;
            // Now we need to re-enable the current controller
            esInput.Flush(); // Try to remove any outstanding events (e.g. Confirm) to not confuse the original controller.
            mainSceneController.SetActive(true);
        }

        void Update()
        {
            // Add support for web interface when we can "deregister" buttons
            if (esInput.GetHeldButtonPress("EyeSkills Up"))
            {
                if (!inEditMode)
                {
                    EnterEditMode();
                }
                else
                {
                    LeaveEditMode();
                }
            }

            // Our menu scrolling
            if ((inEditMode) && esInput.GetShortButtonPress("EyeSkills Up"))
            {
                menuIndex = moveMenuIndexUp(menuIndex);
                audioManager.Say(microControllers[menuIndex].audioID);
            }
            else if ((inEditMode) && esInput.GetShortButtonPress("EyeSkills Down"))
            {
                menuIndex = moveMenuIndexDown(menuIndex);
                audioManager.Say(microControllers[menuIndex].audioID);
            }
            else if ((inEditMode) && esInput.GetShortButtonPress("EyeSkills Confirm"))
            {
                //Activate that micro-controller
                inEditMode = false;
                mc = microControllers[menuIndex].microController;
                //mc.enabled = true; //enable the script (not the game object, which we're also a child of!) This seems to take a cycle to take effect
                esInput.Flush(); // Try to remove any outstanding events (e.g. Confirm) to not confuse the micro controller.
                mc.Startup(this);
            }
        }

        public void MicroControllerShutdown()
        {
            //mainSceneController.GetComponent<EyeSkillsInput>().Flush();
            LeaveEditMode();
            //mc.enabled = false; //disable the microcontroller : Unity DOES NOT like shutting down a script here, as that same script is the callee 
        }
    }
}