using System;
using UnityEngine;


namespace InControl
{
	public class UnknownDeviceBindingSourceListener : BindingSourceListener
	{
		enum DetectPhase : int
		{
			WaitForInitialRelease = 0,
			WaitForControlPress,
			WaitForControlRelease
		}


		UnknownDeviceControl detectFound;
		DetectPhase detectPhase;


		public void Reset()
		{
			detectFound = UnknownDeviceControl.None;
			detectPhase = DetectPhase.WaitForInitialRelease;
			TakeSnapshotOnUnknownDevices();
		}


		void TakeSnapshotOnUnknownDevices()
		{
			var deviceCount = InputManager.Devices.Count;
			for (int i = 0; i < deviceCount; i++)
			{
				var device = InputManager.Devices[i];
				if (device.IsUnknown)
				{
					var unknownDevice = device as UnknownUnityInputDevice;
					if (unknownDevice != null)
					{
						unknownDevice.TakeSnapshot();
					}
				}
			}
		}


		public BindingSource Listen( BindingListenOptions listenOptions, InputDevice device )
		{
			if (!listenOptions.IncludeUnknownControllers || device.IsKnown)
			{
				return null;
			}

			if (detectPhase == DetectPhase.WaitForControlRelease && detectFound)
			{
				if (!IsPressed( detectFound, device ))
				{
					var bindingSource = new UnknownDeviceBindingSource( detectFound );
					Reset();
					return bindingSource;
				}
			}

			var control = ListenForControl( listenOptions, device );
			if (control)
			{
				if (detectPhase == DetectPhase.WaitForControlPress)
				{
					detectFound = control;
					detectPhase = DetectPhase.WaitForControlRelease;
				}
			}
			else
			{
				if (detectPhase == DetectPhase.WaitForInitialRelease)
				{
					detectPhase = DetectPhase.WaitForControlPress;
				}
			}

			return null;
		}


		bool IsPressed( UnknownDeviceControl control, InputDevice device )
		{
			var value = control.GetValue( device );
			return Utility.AbsoluteIsOverThreshold( value, 0.5f );
		}


		UnknownDeviceControl ListenForControl( BindingListenOptions listenOptions, InputDevice device )
		{
			if (device.IsUnknown)
			{
				var unknownDevice = device as UnknownUnityInputDevice;
				if (unknownDevice != null)
				{
					var button = unknownDevice.GetFirstPressedButton();
					if (button)
					{
						return button;
					}

					var analog = unknownDevice.GetFirstPressedAnalog();
					if (analog)
					{
						return analog;
					}
				}
			}

			return UnknownDeviceControl.None;
		}
	}
}

