///////////////////////////////////////////////////////////////////////////////////////////
// DirectInput.h
//
//  Definition of the DirectInput class, which wraps a DirectInput 8 object.

#pragma once

using namespace System;
using namespace System::ComponentModel;

#include "Device.h"
#include "ActionMap.h"

namespace Sunlight
{
    namespace DirectX
    {
        namespace Input
        {
            // Defines arguments for DirectInput-generated events.
            __gc public class DirectInputEventArgs : public EventArgs
            {
            public:
                DirectInputEventArgs(int ID, int Data)
                {
                    this->ID = ID;
                    this->AxisPosition = Data;
                    ButtonPressed = (Data & 0x80) ? true : false;
                }

                int     ID;
                int     AxisPosition;
                bool    ButtonPressed;
            };

            // Wraps an IDirectInput8 object, providing DirectInput functionality.
            __gc public class DirectInput
            {
            protected:
                IDirectInput8   __nogc  *m_pDI;
                DIACTION        __nogc  *m_pActions;
                DIACTIONFORMAT          m_diaf;
                Collections::ArrayList  *m_pDeviceArray;
                bool                    m_bCreated;
                
                System::Windows::Forms::Form    *m_pParentWindow;

                // Enumerates devices and builds the device array.
                virtual void EnumDevices();
                // Builds the DIACTIONFORMAT structure for this object.
                virtual void BuildDIAF();
                // Called when the ParentWindow is activated.
                void OnFormActivated(Object *sender, EventArgs *e);
                // Called when the ParentWindow is deactivated.
                void OnFormDeactivated(Object *sender, EventArgs *e);
                // Creates DirectInput device objects and configure action maps
                void Create();

            public:
                // Callback function to map appropriate devices
                __delegate bool DIEnumDevicesBySemanticsCallbackDelegate(int lpddi, int lpdid, int dwFlags, int dwRemaining, int pvRef);
                bool EnumDevicesBySemanticsCallback(int nddi, int ndid, int dwFlags, int dwRemaining, int pvRef);
                // Callback function to display configuration interface
                __delegate void DIConfigureDevicesCallbackDelegate(int lpDDSTarget, int pvRef);
                void ConfigureDevicesCallback(int lpDDSTarget, int pvRef);

            public:
                // Wraps an IDirectInputDevice8 object in a managed wrapper.
                __gc class Device
                {
                public:
                    Device(IDirectInputDevice8 __nogc *pDevice)
                    {
                        m_pDevice = pDevice;
                        m_pDevice->AddRef();
                    }
                    ~Device()
                    {
                        m_pDevice->Release();
                    }
                    
                    IDirectInputDevice8 __nogc *m_pDevice;
                };

            public:
                DirectInput();
                ~DirectInput();

                // Acquires the devices for use by this application.
                void Acquire();
                // Release the devices for use by other applications.
                void Unacquire();
                // Checks the devices for updated data.
                void Check();
                // Opens a dialog box allowing the user to configure input devices.
                void Configure();
                // Opens a dialog box allowing the user to view the configuration of input devices.
                void Display();
                // Sets/returns the application ID, passed to DirectInput to uniquely identify this application.
                Guid    AppID;
                // Sets/returns the application genre, passed to DirectInput to help it map actions to devices.
                Genres  Genre;
                // Sets/returns the application name, passed to DirectInput to identify this application to the user.
                String  *ActionMapName;
                // Sets/returns the window with which the devices will be associated.
                __property System::Windows::Forms::Form *get_ParentWindow();
                __property void set_ParentWindow(System::Windows::Forms::Form *pParentWindow);
                // Sets/returns the Direct3D device on which the configuration interfaces will be displayed.
                Sunlight::DirectX::Graphics::Device *Direct3DDevice;

                __delegate void ActionEventHandler(DirectInput *sender, DirectInputEventArgs *args);
                // Called when an action event occurs.
                __event ActionEventHandler  *Action;
                // Contains a list of all the event to device action mappings.
                ActionMap           *Actions;
            };
        }
    }
}