using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using DxVBLibA;
using System.Windows.Forms;

namespace KeyConfig
{
	class JoyPad
	{
		//----------// //----------// //----------// //----------//
		//
		//	Constructor
		//
		//----------// //----------// //----------// //----------//

		public JoyPad(int hwnd)
		{
			Program.WriteLog("# JoyPad.ctor");
			Program.WriteLog(String.Format("	hwnd: {0:D}", hwnd));

			DirectXFound = false;
			DirectInputFound = false;
			DeviceFound = false;
			DeviceAcquired = false;

			Program.WriteLog("	DirectX");
			dx8 = new DirectX8Class();
			DirectXFound = true;

			Program.WriteLog("	DirectInput");
			di8 = dx8.DirectInputCreate();
			DirectInputFound = true;

			Program.WriteLog("	CreateGamePad");
			CreateGamePad(hwnd);

			Program.WriteLog("###");
		}

		private void CreateGamePad(int hwnd)
		{
			Program.WriteLog("# CreateGamePad");
			var diEnum = di8.GetDIDevices(CONST_DI8DEVICETYPE.DI8DEVTYPE_JOYSTICK, CONST_DIENUMDEVICESFLAGS.DIEDFL_ATTACHEDONLY);

			try
			{
				if (diEnum.GetCount() >= 1)
				{
					DeviceFound = true;

					Program.WriteLog("	DIEnum");
					var diDeviceInstance = diEnum.GetItem(1);

					try
					{
						Program.WriteLog("	CreateDevice");
						diDevice = di8.CreateDevice(diDeviceInstance.GetGuidInstance());

						Program.WriteLog("	SetCommonDataFormat");
						diDevice.SetCommonDataFormat(CONST_DICOMMONDATAFORMATS.DIFORMAT_JOYSTICK);
						Program.WriteLog("	SetCooperativeLevel");
						diDevice.SetCooperativeLevel(hwnd, CONST_DISCLFLAGS.DISCL_NONEXCLUSIVE | CONST_DISCLFLAGS.DISCL_BACKGROUND | CONST_DISCLFLAGS.DISCL_NOWINKEY);
						Program.WriteLog("	Acquire");
						diDevice.Acquire();
						DeviceAcquired = true;
					}
					catch (Exception ex)
					{
						MessageBox.Show(ex.ToString());
					}
					finally
					{
						Marshal.ReleaseComObject(diDeviceInstance);
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.ToString());
			}
			finally
			{
				Marshal.ReleaseComObject(diEnum);
			}
		}

		//----------// //----------// //----------// //----------//
		//
		//	Destructor
		//
		//----------// //----------// //----------// //----------//

		~JoyPad()
		{
			Dispose(true);
		}

		public void Dispose()
		{
			Dispose(false);
		}

		private void Dispose(bool finalizing)
		{
			Program.WriteLog("# Dispose");

			if (!disposed)
			{
				disposed = true;

				if (diDevice != null)
				{
					Program.WriteLog("	Unacquire");
					diDevice.Unacquire();
					Marshal.ReleaseComObject(diDevice);
				}
				Marshal.ReleaseComObject(di8);
				Marshal.ReleaseComObject(dx8);

				if (!finalizing)
				{
					GC.SuppressFinalize(this);
				}
			}
			Program.WriteLog("###");
		}

		//----------// //----------// //----------// //----------//
		//
		//	Fields
		//
		//----------// //----------// //----------// //----------//

		bool disposed = false;
		DirectX8Class dx8;
		DirectInput8 di8;
		DirectInputDevice8 diDevice;

		//----------// //----------// //----------// //----------//
		//
		//	Methods
		//
		//----------// //----------// //----------// //----------//

		internal List<int> GetPressed()
		{
			if (DeviceFound)
			{
				var list = new List<int>();
				DIJOYSTATE state = new DIJOYSTATE();
				diDevice.GetDeviceStateJoystick(ref state);

				if (state.Buttons != null)
				{
					for (int i = 0; i < state.Buttons.Length; i++)
					{
						if (state.Buttons[i] != 0)
						{
							list.Add(i);
						}
					}
				}
				return list;
			}
			else
			{
				return new List<int>();
			}
		}

		//----------// //----------// //----------// //----------//
		//
		//	Properties
		//
		//----------// //----------// //----------// //----------//

		internal bool DirectXFound { get; set; }

		internal bool DirectInputFound { get; set; }

		internal bool DeviceFound { get; set; }

		internal bool DeviceAcquired { get; set; }
	}
}