using System;
using System.Collections;
using Assets.Scripts.GamepadInterface;
using Assets.Scripts.Terrain;
using UnityEngine;
using UnityEngine.UI;
using XInputDotNetPure;

namespace Assets.Scripts.Gameplay
{
	public class PlayerController : MonoBehaviour
	{
	    public Scripts.Gearbox.GearboxController Gearbox;
	    public SteeringWheelController Player1SteeringWheel;
	    public SteeringWheelController Player2SteeringWheel;

        private PlayerIndex[] _players;
	    private CarController.CarController _car;

		private RandomHornPlayer _randomHorn;
		public GameObject PauseMenu;
	    private PauseMenu _pauseMenu;
	    private bool _holdPause;

	    void Awake()
	    {
	        var player = GameObject.FindGameObjectWithTag("Player");
	        if (player != null) _car = player.GetComponent<CarController.CarController>();
			_randomHorn = FindObjectOfType<RandomHornPlayer> ();
			_pauseMenu = FindObjectOfType<PauseMenu> ();
	    }
        void Start ()
		{
			FindPlayers();
		}

		void FindPlayers()
		{
		    var test = Controller.FindControllers();
		    if (test == null) return;
		    _players = test;
            //todo: check you have 2 controllers connected
        }

        void Update ()
		{
		    if (Input.GetKeyDown(KeyCode.Escape))
		        _pauseMenu.CyclePauseMenu();

            UpdateGamepad();
		}

		void UpdateGamepad()    //This could also go in FixedUpdate
		{
            CheckPlayer1();
            CheckPlayer2();
		}

	    void CheckPlayer1()
	    {
	        var state = Controller.GetState(_players[2]);
	        if (!state.IsConnected) return;
	        Player1SteeringWheel.SetSteeringAngle(state.Left.X, state.Left.Y);
	        _car.Throttle = state.RightTrigger.Value;
	        _car.Brake = state.LeftTrigger.Value;
			if (state.Left.Click.Hold || state.X.Down || state.A.Down || state.B.Down) 
			{
				PlayRandomHorn ();
			}

	    }

        void CheckPlayer2()
	    {
	        var state = Controller.GetState(_players[3]);
	        if (!state.IsConnected) return;
	        Player2SteeringWheel.SetSteeringAngle(state.Left.X, state.Left.Y);
	        state.SetRumble(_players[1], 0f, 0f);
            _car.Clutch = state.LeftTrigger.Value;
	        _car.Brake = state.RightTrigger.Value;
	        state.SetRumble(_players[1], 0f, state.RightTrigger.Value / 2f);
            CheckGearbox(state, state.Right);
            if (state.Y.Hold) TerrainGenerator.Instance.RegenMap();
			if (state.Left.Click.Hold || state.X.Down || state.A.Down || state.B.Down) 
			{
				PlayRandomHorn ();
			}
	    }

		void PlayRandomHorn()
		{
			_randomHorn.PlayRandomSound ();
		}

	    void CheckGearbox(Gamepad state, Gamepad.Stick stick)
	    {
	        var move = Mathf.Abs(stick.X) + Mathf.Abs(stick.Y);
	        if (move < 0.1f) return;

	        if (_car.Clutch < 0.7)
	        {
	            state.SetRumble(_players[1], 0.75f, 0.75f);
	            return;
	        }
	        ChangeGears(stick);
	    }


	    IEnumerator Wait(float time, Action callback)
	    {
            //play sound
	        yield return new WaitForSeconds(time);
	        callback();
	    }

	    void ReenableGear()
	    {
	        Debug.Log("Reenable gear");
	    }


	    void ChangeGears(Gamepad.Stick stick)
	    {
	        var dir = new IntVector2 { X = Mathf.RoundToInt(stick.X), Y = Mathf.RoundToInt(stick.Y) * -1 };
	        _car.Gear = 0;  //take it out of gear
	        Gearbox.ChangeGear(dir, _car);
	    }
	}

    [Serializable]
    public struct IntVector2
    {
        public int X;
        public int Y;
    }
}
	
