/*
 * Joystick testing control panel applet
 *
 * Copyright 2012 Lucas Fialho Zawacki
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 *
 */

#define NONAMELESSUNION
#define COBJMACROS
#define CONST_VTABLE

#include <stdarg.h>
#include <windef.h>
#include <winbase.h>
#include <winuser.h>
#include <commctrl.h>
#include <cpl.h>
#include "ole2.h"

#include "wine/debug.h"
#include "joy.h"

WINE_DEFAULT_DEBUG_CHANNEL(joycpl);

DECLSPEC_HIDDEN HMODULE hcpl;

/*********************************************************************
 *  DllMain
 */
BOOL WINAPI DllMain(HINSTANCE hdll, DWORD reason, LPVOID reserved)
{
    TRACE("(%p, %d, %p)\n", hdll, reason, reserved);

    switch (reason)
    {
        case DLL_WINE_PREATTACH:
            return FALSE;  /* prefer native version */

        case DLL_PROCESS_ATTACH:
            DisableThreadLibraryCalls(hdll);
            hcpl = hdll;
    }
    return TRUE;
}

/***********************************************************************
 *  enum_callback [internal]
 *   Enumerates, creates and sets the common data format for all the joystick devices.
 *   First time it checks if space for the joysticks was already reserved
 *   and if not, just counts how many there are.
 */
static BOOL CALLBACK enum_callback(const DIDEVICEINSTANCEW *instance, void *context)
{
    struct JoystickData *data = context;
    struct Joystick *joystick;
    DIDEVCAPS caps;

    if (data->joysticks == NULL)
    {
        data->num_joysticks += 1;
        return DIENUM_CONTINUE;
    }

    joystick = &data->joysticks[data->cur_joystick];
    data->cur_joystick += 1;

    IDirectInput8_CreateDevice(data->di, &instance->guidInstance, &joystick->device, NULL);
    IDirectInputDevice8_SetDataFormat(joystick->device, &c_dfDIJoystick);

    joystick->instance = *instance;

    caps.dwSize = sizeof(caps);
    IDirectInputDevice8_GetCapabilities(joystick->device, &caps);

    joystick->num_buttons = caps.dwButtons;
    joystick->num_axes = caps.dwAxes;

    return DIENUM_CONTINUE;
}

/***********************************************************************
 *  initialize_joysticks [internal]
 */
static void initialize_joysticks(struct JoystickData *data)
{
    data->num_joysticks = 0;
    data->cur_joystick = 0;
    IDirectInput8_EnumDevices(data->di, DI8DEVCLASS_GAMECTRL, enum_callback, data, DIEDFL_ATTACHEDONLY);
    data->joysticks = HeapAlloc(GetProcessHeap(), 0, sizeof(struct Joystick) * data->num_joysticks);

    /* Get all the joysticks */
    IDirectInput8_EnumDevices(data->di, DI8DEVCLASS_GAMECTRL, enum_callback, data, DIEDFL_ATTACHEDONLY);
}

/***********************************************************************
 *  destroy_joysticks [internal]
 */
static void destroy_joysticks(struct JoystickData *data)
{
    int i;

    for (i = 0; i < data->num_joysticks; i++)
    {
        IDirectInputDevice8_Unacquire(data->joysticks[i].device);
        IDirectInputDevice8_Release(data->joysticks[i].device);
    }

    HeapFree(GetProcessHeap(), 0, data->joysticks);
}

/*********************************************************************
 * list_dlgproc [internal]
 *
 */
INT_PTR CALLBACK list_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    TRACE("(%p, 0x%08x/%d, 0x%lx)\n", hwnd, msg, msg, lparam);
    switch (msg)
    {
        case WM_INITDIALOG:
        {
            int i;
            struct JoystickData *data = (struct JoystickData*) ((PROPSHEETPAGEW*)lparam)->lParam;

            /* Set dialog information */
            for (i = 0; i < data->num_joysticks; i++)
            {
                struct Joystick *joy = &data->joysticks[i];
                SendDlgItemMessageW(hwnd, IDC_JOYSTICKLIST, LB_ADDSTRING, 0, (LPARAM) joy->instance.tszInstanceName);
            }

            return TRUE;
        }

        case WM_COMMAND:

            switch (LOWORD(wparam))
            {
                case IDC_BUTTONDISABLE:
                    FIXME("Disable selected joystick from being enumerated\n");
                    break;

                case IDC_BUTTONENABLE:
                    FIXME("Re-Enable selected joystick\n");
                    break;
            }

            return TRUE;

        case WM_NOTIFY:
            return TRUE;

        default:
            break;
    }
    return FALSE;
}

/*********************************************************************
 * Joystick testing functions
 *
 */
static void dump_joy_state(DIJOYSTATE* st, int num_buttons)
{
    int i;
    TRACE("Ax (% 5d,% 5d,% 5d)\n", st->lX,st->lY, st->lZ);
    TRACE("RAx (% 5d,% 5d,% 5d)\n", st->lRx, st->lRy, st->lRz);
    TRACE("Slider (% 5d,% 5d)\n", st->rglSlider[0], st->rglSlider[1]);
    TRACE("Pov (% 5d,% 5d,% 5d,% 5d)\n", st->rgdwPOV[0], st->rgdwPOV[1], st->rgdwPOV[2], st->rgdwPOV[3]);

    TRACE("Buttons ");
    for(i=0; i < num_buttons; i++)
        TRACE("  %c",st->rgbButtons[i] ? 'x' : 'o');
    TRACE("\n");
}

static void poll_input(const struct Joystick *joy, DIJOYSTATE *state)
{
    HRESULT  hr;

    hr = IDirectInputDevice8_Poll(joy->device);

    /* If it failed, try to acquire the joystick */
    if (FAILED(hr))
    {
        hr = IDirectInputDevice8_Acquire(joy->device);
        while (hr == DIERR_INPUTLOST) hr = IDirectInputDevice8_Acquire(joy->device);
    }

    if (hr == DIERR_OTHERAPPHASPRIO) return;

    IDirectInputDevice8_GetDeviceState(joy->device, sizeof(DIJOYSTATE), state);
}

static DWORD WINAPI input_thread(void *param)
{
    int axes_pos[TEST_MAX_AXES][2];
    DIJOYSTATE state;
    struct JoystickData *data = param;

    ZeroMemory(&state, sizeof(state));

    while (!data->stop)
    {
        int i;
        poll_input(&data->joysticks[data->chosen_joystick], &state);

        dump_joy_state(&state, data->joysticks[data->chosen_joystick].num_buttons);

        /* Indicate pressed buttons */
        for (i = 0; i < data->joysticks[data->chosen_joystick].num_buttons; i++)
            if (state.rgbButtons[i])
                SendMessageW(data->buttons[i], BM_SETSTATE, TRUE, 0);

        /* Indicate axis positions, axes showing are hardcoded for now */
        axes_pos[0][0] = state.lX;
        axes_pos[0][1] = state.lY;
        axes_pos[1][0] = state.lRx;
        axes_pos[1][1] = state.lRy;
        axes_pos[2][0] = state.lZ;
        axes_pos[2][1] = state.lRz;

        for (i = 0; i < TEST_MAX_AXES; i++)
            SetWindowPos(data->axes[i], 0,
                        TEST_AXIS_X + TEST_NEXT_AXIS_X*i + axes_pos[i][0],
                        TEST_AXIS_Y + axes_pos[i][1],
                        0, 0, SWP_NOZORDER | SWP_NOSIZE);

        Sleep(TEST_POLL_TIME);

        /* Reset button state */
        for (i = 0; i < data->joysticks[data->chosen_joystick].num_buttons; i++)
            SendMessageW(data->buttons[i], BM_SETSTATE, FALSE, 0);
    }

    return 0;
}

static void test_handle_joychange(HWND hwnd, struct JoystickData *data)
{
    int i;

    if (data->num_joysticks == 0) return;

    data->chosen_joystick = SendDlgItemMessageW(hwnd, IDC_TESTSELECTCOMBO, CB_GETCURSEL, 0, 0);

    /* Enable only  buttons present in the device */
    for (i = 0; i < TEST_MAX_BUTTONS; i++)
        ShowWindow(data->buttons[i], i <= data->joysticks[data->chosen_joystick].num_buttons);
}

/*********************************************************************
 * button_number_to_wchar [internal]
 *  Transforms an integer in the interval [0,99] into a 2 character WCHAR string
 */
static void button_number_to_wchar(int n, WCHAR str[3])
{
    str[1] = n % 10 + '0';
    n /= 10;
    str[0] = n % 10 + '0';
    str[2] = '\0';
}

static void draw_joystick_buttons(HWND hwnd, struct JoystickData* data)
{
    int i;
    int row = 0, col = 0;
    WCHAR button_label[3];
    HINSTANCE hinst = (HINSTANCE) GetWindowLongPtrW(hwnd, GWLP_HINSTANCE);
    static WCHAR button_class[] = {'B','u','t','t','o','n','\0'};

    for (i = 0; i < TEST_MAX_BUTTONS; i++)
    {
        if ((i % TEST_BUTTON_COL_MAX) == 0 && i != 0)
        {
            row += 1;
            col = 0;
        }

        button_number_to_wchar(i + 1, button_label);

        data->buttons[i] = CreateWindowW(button_class, button_label, WS_CHILD,
            TEST_BUTTON_X + TEST_NEXT_BUTTON_X*col, TEST_BUTTON_Y + TEST_NEXT_BUTTON_Y*row,
            TEST_BUTTON_SIZE_X, TEST_BUTTON_SIZE_Y,
            hwnd, NULL, NULL, hinst);

        col += 1;
    }
}

static void draw_joystick_axes(HWND hwnd, struct JoystickData* data)
{
    int i;
    struct Joystick *joy;
    DIPROPRANGE propRange;
    HINSTANCE hinst = (HINSTANCE) GetWindowLongPtrW(hwnd, GWLP_HINSTANCE);
    static WCHAR button_class[] = {'B','u','t','t','o','n','\0'};

    /* Set axis range to ease the GUI visualization */
    for (i = 0; i < data->num_joysticks; i++)
    {
        joy = &data->joysticks[i];
        propRange.diph.dwSize = sizeof(DIPROPRANGE);
        propRange.diph.dwHeaderSize = sizeof(DIPROPHEADER);
        propRange.diph.dwHow = DIPH_DEVICE;
        propRange.diph.dwObj = 0;
        propRange.lMin = TEST_AXIS_MIN;
        propRange.lMax = TEST_AXIS_MAX;

        IDirectInputDevice_SetProperty(joy->device, DIPROP_RANGE, &propRange.diph);
    }

    for (i = 0; i < TEST_MAX_AXES; i++)
    {
        data->axes[i] = CreateWindowW( button_class, NULL, WS_CHILD | WS_VISIBLE,
            TEST_AXIS_X + TEST_NEXT_AXIS_X*i, TEST_AXIS_Y,
            TEST_AXIS_SIZE_X, TEST_AXIS_SIZE_Y,
            hwnd, (HMENU) IDC_JOYSTICKAXES + i, NULL, hinst);
    }
}

/*********************************************************************
 * test_dlgproc [internal]
 *
 */
static INT_PTR CALLBACK test_dlgproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    static HANDLE thread;
    static struct JoystickData *data;
    TRACE("(%p, 0x%08x/%d, 0x%lx)\n", hwnd, msg, msg, lparam);

    switch (msg)
    {
        case WM_INITDIALOG:
        {
            int i;

            data = (struct JoystickData*) ((PROPSHEETPAGEW*)lparam)->lParam;

            /* Add enumerated joysticks to the combobox */
            for (i = 0; i < data->num_joysticks; i++)
            {
                struct Joystick *joy = &data->joysticks[i];
                SendDlgItemMessageW(hwnd, IDC_TESTSELECTCOMBO, CB_ADDSTRING, 0, (LPARAM) joy->instance.tszInstanceName);
            }

            draw_joystick_buttons(hwnd, data);
            draw_joystick_axes(hwnd, data);

            return TRUE;
        }

        case WM_COMMAND:
            switch(wparam)
            {
                case MAKEWPARAM(IDC_TESTSELECTCOMBO, CBN_SELCHANGE):
                    test_handle_joychange(hwnd, data);
                break;
            }
            return TRUE;

        case WM_NOTIFY:
            switch(((LPNMHDR)lparam)->code)
            {
                case PSN_SETACTIVE:
                {
                    DWORD tid;

                    /* Initialize input thread */
                    if (data->num_joysticks > 0)
                    {
                        data->stop = FALSE;

                        /* Set the first joystick as default */
                        SendDlgItemMessageW(hwnd, IDC_TESTSELECTCOMBO, CB_SETCURSEL, 0, 0);
                        test_handle_joychange(hwnd, data);

                        thread = CreateThread(NULL, 0, input_thread, (void*) data, 0, &tid);
                    }
                }
                break;

                case PSN_RESET:
                    /* Stop input thread */
                    data->stop = TRUE;
                    CloseHandle(thread);
                break;
            }
            return TRUE;
    }
    return FALSE;
}

/******************************************************************************
 * propsheet_callback [internal]
 */
static int CALLBACK propsheet_callback(HWND hwnd, UINT msg, LPARAM lparam)
{
    TRACE("(%p, 0x%08x/%d, 0x%lx)\n", hwnd, msg, msg, lparam);
    switch (msg)
    {
        case PSCB_INITIALIZED:
            break;
    }
    return 0;
}

/******************************************************************************
 * display_cpl_sheets [internal]
 *
 * Build and display the dialog with all control panel propertysheets
 *
 */
static void display_cpl_sheets(HWND parent, struct JoystickData *data)
{
    INITCOMMONCONTROLSEX icex;
    PROPSHEETPAGEW psp[NUM_PROPERTY_PAGES];
    PROPSHEETHEADERW psh;
    DWORD id = 0;

    OleInitialize(NULL);
    /* Initialize common controls */
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_LISTVIEW_CLASSES | ICC_BAR_CLASSES;
    InitCommonControlsEx(&icex);

    ZeroMemory(&psh, sizeof(psh));
    ZeroMemory(psp, sizeof(psp));

    /* Fill out all PROPSHEETPAGE */
    psp[id].dwSize = sizeof (PROPSHEETPAGEW);
    psp[id].hInstance = hcpl;
    psp[id].u.pszTemplate = MAKEINTRESOURCEW(IDD_LIST);
    psp[id].pfnDlgProc = list_dlgproc;
    psp[id].lParam = (INT_PTR) data;
    id++;

    psp[id].dwSize = sizeof (PROPSHEETPAGEW);
    psp[id].hInstance = hcpl;
    psp[id].u.pszTemplate = MAKEINTRESOURCEW(IDD_TEST);
    psp[id].pfnDlgProc = test_dlgproc;
    psp[id].lParam = (INT_PTR) data;
    id++;

    psp[id].dwSize = sizeof (PROPSHEETPAGEW);
    psp[id].hInstance = hcpl;
    psp[id].u.pszTemplate = MAKEINTRESOURCEW(IDD_FORCEFEEDBACK);
    psp[id].pfnDlgProc = NULL;
    psp[id].lParam = (INT_PTR) data;
    id++;

    /* Fill out the PROPSHEETHEADER */
    psh.dwSize = sizeof (PROPSHEETHEADERW);
    psh.dwFlags = PSH_PROPSHEETPAGE | PSH_USEICONID | PSH_USECALLBACK;
    psh.hwndParent = parent;
    psh.hInstance = hcpl;
    psh.pszCaption = MAKEINTRESOURCEW(IDS_CPL_NAME);
    psh.nPages = id;
    psh.u3.ppsp = psp;
    psh.pfnCallback = propsheet_callback;

    /* display the dialog */
    PropertySheetW(&psh);

    OleUninitialize();
}

/*********************************************************************
 * CPlApplet (joy.cpl.@)
 *
 * Control Panel entry point
 *
 * PARAMS
 *  hWnd    [I] Handle for the Control Panel Window
 *  command [I] CPL_* Command
 *  lParam1 [I] first extra Parameter
 *  lParam2 [I] second extra Parameter
 *
 * RETURNS
 *  Depends on the command
 *
 */
LONG CALLBACK CPlApplet(HWND hwnd, UINT command, LPARAM lParam1, LPARAM lParam2)
{
    static struct JoystickData data;
    TRACE("(%p, %u, 0x%lx, 0x%lx)\n", hwnd, command, lParam1, lParam2);

    switch (command)
    {
        case CPL_INIT:
        {
            HRESULT hr;

            /* Initialize dinput */
            hr = DirectInput8Create(GetModuleHandleW(NULL), DIRECTINPUT_VERSION, &IID_IDirectInput8W, (void**)&data.di, NULL);

            if (FAILED(hr))
            {
                ERR("Failed to initialize DirectInput: 0x%08x\n", hr);
                return FALSE;
            }

            /* Then get all the connected joysticks */
            initialize_joysticks(&data);

            return TRUE;
        }
        case CPL_GETCOUNT:
            return 1;

        case CPL_INQUIRE:
        {
            CPLINFO *appletInfo = (CPLINFO *) lParam2;

            appletInfo->idName = IDS_CPL_NAME;
            appletInfo->idInfo = IDS_CPL_INFO;
            appletInfo->lData = 0;
            return TRUE;
        }

        case CPL_DBLCLK:
            display_cpl_sheets(hwnd, &data);
            break;

        case CPL_STOP:
            destroy_joysticks(&data);

            /* And destroy dinput too */
            IDirectInput8_Release(data.di);
            break;
    }

    return FALSE;
}
