﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace Nostalgia.Example
{
	public sealed class VirtualInput : MonoBehaviour
	{
		private static VirtualInput _Instance = null;

		public static bool enableVirtualPad
		{
			get
			{
				return _Instance != null && _Instance._RuntimeMode == Mode.VirtualPad;
			}
		}

		public static float GetAxis(string axisName)
		{
			if (enableVirtualPad)
			{
				return _Instance.Internal_GetAxis(axisName);
			}

			return Input.GetAxis(axisName);
		}

		public static float GetAxisRaw(string axisName)
		{
			if (enableVirtualPad)
			{
				return _Instance.Internal_GetAxis(axisName);
			}

			return Input.GetAxisRaw(axisName);
		}

		public static void ResetInputAxes()
		{
			if (enableVirtualPad)
			{
				return;
			}

			Input.ResetInputAxes();
		}

		public static bool GetButton(string buttonName)
		{
			if (enableVirtualPad)
			{
				return _Instance.Internal_GetButton(buttonName);
			}

			return Input.GetButton(buttonName);
		}

		public static bool GetButtonDown(string buttonName)
		{
			if (enableVirtualPad)
			{
				return _Instance.Internal_GetButtonDown(buttonName);
			}

			return Input.GetButtonDown(buttonName);
		}

		public enum Mode
		{
			Auto = -1,

			UnityInput,
			VirtualPad,
		}

		[SerializeField]
		private Mode _Mode = Mode.Auto;

		[SerializeField]
		private GameObject _VirtualPad;

		[SerializeField]
		private Joystick _Joystick;

		[SerializeField]
		private GameObject _Buttons;

		private Mode _RuntimeMode;

		private Dictionary<string, ButtonController> _ButtonControllers = new Dictionary<string, ButtonController>();

		static bool IsMobile()
		{
			if (Application.platform == RuntimePlatform.Android ||
					Application.platform == RuntimePlatform.IPhonePlayer)
			{
				return true;
			}

#if UNITY_EDITOR
			if (UnityEditor.EditorApplication.isRemoteConnected)
			{
				return true;
			}
#endif

			return false;
		}

		private void Awake()
		{
			_Instance = this;

			if (_Mode == Mode.Auto)
			{
				if (IsMobile())
				{
					_RuntimeMode = Mode.VirtualPad;
				}
				else
				{
					_RuntimeMode = Mode.UnityInput;
				}
			}
			else
			{
				_RuntimeMode = _Mode;
			}

			switch (_RuntimeMode)
			{
				case Mode.UnityInput:
					if (_VirtualPad != null)
					{
						_VirtualPad.SetActive(false);
					}
					break;
				case Mode.VirtualPad:
					if (_VirtualPad != null)
					{
						_VirtualPad.SetActive(true);
					}
					break;
			}

			foreach (var buttonController in _Buttons.GetComponentsInChildren<ButtonController>())
			{
				_ButtonControllers.Add(buttonController.gameObject.name, buttonController);
			}
		}

		private float Internal_GetAxis(string axisName)
		{
			switch (axisName)
			{
				case "Horizontal":
					return _Joystick.horizontal;
				case "Vertical":
					return _Joystick.vertical;
			}

			return 0f;
		}

		private bool Internal_GetButtonDown(string buttonName)
		{
			if (_ButtonControllers.TryGetValue(buttonName, out ButtonController buttonController))
			{
				return buttonController.status == ButtonController.Status.Down;
			}

			return false;
		}

		private bool Internal_GetButton(string buttonName)
		{
			if (_ButtonControllers.TryGetValue(buttonName, out ButtonController buttonController))
			{
				return buttonController.press;
			}

			return false;
		}
	}
}