/***************************************************************************

  DIMouse.c

 ***************************************************************************/

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include <dinput.h>
#include "win32.h"
#include "mouse.h"
#include "DirectInput.h"
#include "DIMouse.h"


static int    DIMouse_init(options_type *osd_options);
static void   DIMouse_exit(void);

static void   DIMouse_trak_read(int player, int *deltax, int *deltay);
static int    DIMouse_trak_pressed(enum ETrakCode eTrakCode);
static BOOL   DIMouse_OnMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT* pResult);
static void   OnActivateApp(HWND hWnd, BOOL fActivate, DWORD dwThreadId);

static void   DIMouse_poll_mouse(void);


struct OSDMouse  DIMouse =
{
    DIMouse_init,           /* init            */
    DIMouse_exit,           /* exit            */

    DIMouse_trak_read,      /* trak_read       */
    DIMouse_trak_pressed,   /* trak_pressed    */
    DIMouse_poll_mouse,     /* poll_mouse      */

    DIMouse_OnMessage,      /* OnMessage       */
};

static LPDIRECTINPUTDEVICE  didmouse;
static DIMOUSESTATE         status;
static BOOL                 use_axes;


static int DIMouse_init(options_type *osd_options)
{
    HRESULT hr;
    DIPROPDWORD dwDIProp;

    didmouse = NULL;
    use_axes = osd_options->use_mouse;

    if (di == NULL)
        return 1;

    /* setup the mouse */
    hr = IDirectInput_CreateDevice(di, &GUID_SysMouse, &didmouse, NULL);
    if (hr != DI_OK) return 1;

    dwDIProp.diph.dwSize = sizeof(DIPROPDWORD);
    dwDIProp.diph.dwHeaderSize = sizeof(dwDIProp.diph);
    dwDIProp.diph.dwObj = 0;
    dwDIProp.diph.dwHow = DIPH_DEVICE;
    dwDIProp.dwData = DIPROPAXISMODE_REL;
    hr = IDirectInputDevice_SetProperty(didmouse, DIPROP_AXISMODE, &dwDIProp.diph);
    if (hr != DI_OK) return 1;

    hr = IDirectInputDevice_SetDataFormat(didmouse, &c_dfDIMouse);
    if (hr != DI_OK) return 1;

    hr = IDirectInputDevice_SetCooperativeLevel(didmouse, MAME32App.m_hWnd,
                                                 DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
    if (hr != DI_OK) return 1;

    hr = IDirectInputDevice_Acquire(didmouse);

    if (use_axes)
        ShowCursor(FALSE);

    return 0;
}


static void DIMouse_exit(void)
{
    if (!didmouse)
        return;

    IDirectInputDevice_Unacquire(didmouse);
    IDirectInputDevice_Release(didmouse);

    didmouse = NULL;

    if (use_axes)
        ShowCursor(TRUE);
}


static void DIMouse_trak_read(int player, int *deltax, int *deltay)
{
    if (player == 0 && use_axes)
    {
        *deltax = status.lX;
        *deltay = status.lY;
    }
    else
        *deltax = *deltay = 0;

}


static int DIMouse_trak_pressed(enum ETrakCode eTrakCode)
{
    switch (eTrakCode)
    {
        case TRAK_FIRE1:
        case TRAK_FIRE2:
        case TRAK_FIRE3:
        case TRAK_FIRE4:
        case TRAK_FIRE5:
            return (status.rgbButtons[eTrakCode - 1] & 0x80) != 0;

        case TRAK_FIRE_ANY:
            return ((status.rgbButtons[0] |
                     status.rgbButtons[1] |
                     status.rgbButtons[2] |
                     status.rgbButtons[3] |
                     status.rgbButtons[4]) & 0x80) != 0;

        default:
            return 0;
    }
}


static void DIMouse_poll_mouse(void)
{
    HRESULT hr;

    if (didmouse == NULL)
       return;

again:
    hr = IDirectInputDevice_GetDeviceState(didmouse, sizeof(DIMOUSESTATE), &status);
    if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED)
    {
        hr = IDirectInputDevice_Acquire(didmouse);
        if (hr == DI_OK)
            goto again;
    }
}


static BOOL DIMouse_OnMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
    switch (Msg)
    {
        PEEK_MESSAGE(hWnd, WM_ACTIVATEAPP,  OnActivateApp);
    }
    return FALSE;
}


static void OnActivateApp(HWND hWnd, BOOL fActivate, DWORD dwThreadId)
{
    if (!didmouse)
        return;

    if (MAME32App.m_bIsActive == TRUE)
        IDirectInputDevice_Acquire(didmouse);
    else
        IDirectInputDevice_Unacquire(didmouse);
}
