using InControl;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    public Action<int> OnStartPress;
    public Action<int> OnSubmitPress;
    public Action<int> OnBackPress;
    public Action<int> OnSpecialPress;
    public Action<int, int> OnHorizontalDPadPress;
    public Action<int, int> OnVerticalDPadPress;

    public Action<int> OnControllerAttach;
    public Action<int> OnControllerDetach;
    public Action<InputDevice[], bool> OnControllersChanged;

    private Dictionary<InputDevice, int> devicesToIDs;
    private Dictionary<int, InputDevice> IDsToDevices;
    private Stack<int> freeIDs;

    public List<int> ControllerIDs { get { return IDsToDevices.Keys.ToList(); } }
    public int ControllerCount { get { return ControllerIDs.Count; } }

    [SerializeField] private BombController bombController;
    public BombController BombController { get {return bombController; } }
    //public GameStart GameStart { get; set; }

    public static GameManager Instance { get; private set; }


    private void Awake ()
    {
        //Debug.Log(GetValueInRange(15, 0, 30, 0, 15));


        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(this.gameObject);
        }
    }
    private void Start()
    {
        //bombController = GameObject.Find("bomb1").GetComponent<BombController>();

        freeIDs = new Stack<int>( new int[4] { 3, 2, 1, 0} );
        devicesToIDs = new Dictionary<InputDevice, int>(4);
        IDsToDevices = new Dictionary<int, InputDevice>(4);

        InputManager.OnDeviceAttached += OnDeviceAttached;
        InputManager.OnDeviceDetached += OnDeviceDetached;

        foreach (InputDevice device in InputManager.Devices)
        {
            OnDeviceAttached(device);
        }

        // SceneManager.LoadScene(SceneNames.Start_Intro.ToString());
    }
    private void Update()
    {
        // if (SceneChanger.Instance.SwitchingScenes) return;

        foreach (InputDevice device in devicesToIDs.Keys)
        {
            if (device.MenuWasPressed)
            {
                if (OnStartPress != null) OnStartPress(devicesToIDs[device]);
            }
            else if (device.Action1.WasPressed)
            {
                if (OnSubmitPress != null) OnSubmitPress(devicesToIDs[device]);
            }
            else if (device.Action2.WasPressed)
            {
                if (OnBackPress != null) OnBackPress(devicesToIDs[device]);
            }
            else if (device.Action4.WasPressed)
            {
                if (OnSpecialPress != null) OnSpecialPress(devicesToIDs[device]);
            }
            else if (device.DPadLeft.WasPressed)
            {
                if (OnHorizontalDPadPress != null) OnHorizontalDPadPress(devicesToIDs[device], -1);
            }
            else if (device.DPadRight.WasPressed)
            {
                if (OnHorizontalDPadPress != null) OnHorizontalDPadPress(devicesToIDs[device], 1);
            }
            else if (device.DPadUp.WasPressed)
            {
                if (OnVerticalDPadPress != null) OnVerticalDPadPress(devicesToIDs[device], 1);
            }
            else if (device.DPadDown.WasPressed)
            {
                if (OnVerticalDPadPress != null) OnVerticalDPadPress(devicesToIDs[device], -1);
            }
        }
    }

    public int GetControllerID(InputDevice device)
    {
        int controllerID;
        if (devicesToIDs.TryGetValue(device, out controllerID))
        {
            return controllerID;
        }
        else
        {
            Debug.LogWarning(device.Name + "isn't bound to an ID");
            return -1;
        }
    }
    public InputDevice GetControllerDevice(int id)
    {
        InputDevice device;
        if (IDsToDevices.TryGetValue(id, out device))
        {
            return device;
        }
        else
        {
            Debug.LogWarning(id + "isn't used by any device");
            return null;
        }
    }
    public void TriggerControllerUpdate(bool allowUIInput)
    {
        if (OnControllersChanged != null) OnControllersChanged(devicesToIDs.Keys.ToArray(), allowUIInput);
    }

    public void RegisterBomb(BombController bomb)
    {
        bombController = bomb;
    }


    private void OnDeviceAttached(InputDevice device)
    {
        if (!devicesToIDs.ContainsKey(device))
        {
            if (freeIDs.Count == 0)
            {
                Debug.LogWarning("Game only supports 4 controllers");
                return;
            }

            int id = freeIDs.Pop();
            devicesToIDs.Add(device, id);
            IDsToDevices.Add(id, device);
            if (OnControllersChanged != null) OnControllersChanged(devicesToIDs.Keys.ToArray(), true);
            if (OnControllerAttach != null) OnControllerAttach(id);
            Debug.LogWarning(device.Name + " was attached");
        }
    }
    private void OnDeviceDetached(InputDevice device)
    {
        int id;
        if (devicesToIDs.TryGetValue(device, out id))
        {
            freeIDs.Push(id);
            devicesToIDs.Remove(device);
            IDsToDevices.Remove(id);
            if (OnControllersChanged != null) OnControllersChanged(devicesToIDs.Keys.ToArray(), true);
            if (OnControllerDetach != null) OnControllerDetach(id);
            Debug.LogWarning(device.Name + " was detached");
        }
    }

    public float GetValueInRange(float value, float myMinRange, float myMaxRange, float newMinRange, float newMaxRange)
    {
        return (value - myMinRange) * (newMaxRange - newMinRange)/(myMaxRange - myMinRange) + newMinRange;
    }
}