/*
 * Copyright (c) 2011 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

#include "wine/unicode.h"
#include "objbase.h"
#include "dinput_private.h"
#include "device_private.h"
#include "resource.h"

typedef struct {
    int nobjects;
    IDirectInputDevice8W *lpdid;
    DIDEVICEINSTANCEW ddi;
    DIDEVICEOBJECTINSTANCEW ddo[256];
} DeviceData;

typedef struct {
    int ndevices;
    DeviceData *devices;
} DIDevicesData;

typedef struct {
    IDirectInput8W *lpDI;
    LPDIACTIONFORMATW lpdiaf;
    LPDIACTIONFORMATW original_lpdiaf;
    DIDevicesData devices_data;
    int display_only;
} ConfigureDevicesData;

/*
 * Enumeration callback functions
 */
static BOOL CALLBACK collect_objects(LPCDIDEVICEOBJECTINSTANCEW lpddo, LPVOID pvRef)
{
    DeviceData *data = (DeviceData*) pvRef;

    data->ddo[data->nobjects] = *lpddo;

    data->nobjects++;
    return DIENUM_CONTINUE;
}

static BOOL CALLBACK count_devices(LPCDIDEVICEINSTANCEW lpddi, IDirectInputDevice8W *lpdid, DWORD dwFlags, DWORD dwRemaining, LPVOID pvRef)
{
    DIDevicesData *data = (DIDevicesData*) pvRef;

    data->ndevices++;
    return DIENUM_CONTINUE;
}

static BOOL CALLBACK collect_devices(LPCDIDEVICEINSTANCEW lpddi, IDirectInputDevice8W *lpdid, DWORD dwFlags, DWORD dwRemaining, LPVOID pvRef)
{
    DIDevicesData *data = (DIDevicesData*) pvRef;
    DeviceData *device = &data->devices[data->ndevices];
    device->lpdid = lpdid;
    device->ddi = *lpddi;

    IDirectInputDevice_AddRef(lpdid);

    device->nobjects = 0;
    IDirectInputDevice_EnumObjects(lpdid, collect_objects, (LPVOID) device, DIDFT_ALL);

    data->ndevices++;
    return DIENUM_CONTINUE;
}

/*
 * Listview utility functions
 */
static void init_listview_columns(HWND dialog)
{
    HINSTANCE hinstance = (HINSTANCE) GetWindowLongPtrW(dialog, GWLP_HINSTANCE);
    LVCOLUMNW listColumn;
    RECT viewRect;
    int width;
    WCHAR column[MAX_PATH];

    GetClientRect(GetDlgItem(dialog, IDC_DEVICEOBJECTSLIST), &viewRect);
    width = (viewRect.right - viewRect.left)/2;

    LoadStringW(hinstance, IDS_OBJECTCOLUMN, column, sizeof(column)/sizeof(column[0]));
    listColumn.mask = LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
    listColumn.pszText = column;
    listColumn.cchTextMax = lstrlenW(listColumn.pszText);
    listColumn.cx = width;

    SendDlgItemMessageW (dialog, IDC_DEVICEOBJECTSLIST, LVM_INSERTCOLUMNW, 0, (LPARAM) &listColumn);

    LoadStringW(hinstance, IDS_ACTIONCOLUMN, column, sizeof(column)/sizeof(column[0]));
    listColumn.cx = width;
    listColumn.pszText = column;
    listColumn.cchTextMax = lstrlenW(listColumn.pszText);

    SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_INSERTCOLUMNW, 1, (LPARAM) &listColumn);
}

static int lv_get_cur_item(HWND dialog)
{
    return SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
}

static int lv_get_item_data(HWND dialog, int index)
{
    LVITEMW item;

    if (index < 0) return -1;

    item.mask = LVIF_PARAM;
    item.iItem = index;
    item.iSubItem = 0;

    SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_GETITEMW , 0, (LPARAM)&item);

    return item.lParam;
}

static void lv_set_action(HWND dialog, int item, int action, LPDIACTIONFORMATW lpdiaf)
{
    static const WCHAR no_action[] = {'-','\0'};
    const WCHAR *action_text = no_action;
    LVITEMW lvItem;

    if (item < 0) return;

    if (action != -1)
        action_text = lpdiaf->rgoAction[action].u.lptszActionName;

    /* Keep the action and text in the listview item */
    lvItem.iItem = item;

    lvItem.mask = LVIF_PARAM;
    lvItem.iSubItem = 0;
    lvItem.lParam = (LPARAM) action;

    /* Action index */
    SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_SETITEMW, 0, (LPARAM) &lvItem);

    lvItem.mask = LVIF_TEXT;
    lvItem.iSubItem = 1;
    lvItem.pszText = (WCHAR *)action_text;
    lvItem.cchTextMax = lstrlenW(lvItem.pszText);

    /* Text */
    SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_SETITEMW, 0, (LPARAM) &lvItem);
}

/*
 * Utility functions
 */
static DeviceData* get_cur_device(HWND dialog)
{
    ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
    int sel = SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_GETCURSEL, 0, 0);
    return &data->devices_data.devices[sel];
}

static LPDIACTIONFORMATW get_cur_lpdiaf(HWND dialog)
{
    ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
    return data->lpdiaf;
}

static int dialog_display_only(HWND dialog)
{
    ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
    return data->display_only;
}

static void init_devices(HWND dialog, IDirectInput8W *lpDI, DIDevicesData *data, LPDIACTIONFORMATW lpdiaf)
{
    int i;

    /* Count devices */
    data->ndevices = 0;
    IDirectInput8_EnumDevicesBySemantics(lpDI, NULL, lpdiaf, count_devices, (LPVOID) data, 0);

    /* Allocate devices */
    data->devices = HeapAlloc(GetProcessHeap(), 0, sizeof(DeviceData) * data->ndevices);

    /* Collect and insert */
    data->ndevices = 0;
    IDirectInput8_EnumDevicesBySemantics(lpDI, NULL, lpdiaf, collect_devices, (LPVOID) data, 0);

    for (i=0; i < data->ndevices; i++)
        SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_ADDSTRING, 0, (LPARAM) data->devices[i].ddi.tszProductName );
}

static void destroy_data(HWND dialog)
{
    int i;
    ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
    DIDevicesData *devices_data = &data->devices_data;

    /* Free the devices */
    for (i=0; i < devices_data->ndevices; i++)
        IDirectInputDevice8_Release(devices_data->devices[i].lpdid);

    HeapFree(GetProcessHeap(), 0, devices_data->devices);

    /* Free the backup LPDIACTIONFORMATW  */
    HeapFree(GetProcessHeap(), 0, data->original_lpdiaf->rgoAction);
    HeapFree(GetProcessHeap(), 0, data->original_lpdiaf);
}

static void fill_device_object_list(HWND dialog)
{
    DeviceData *device = get_cur_device(dialog);
    LPDIACTIONFORMATW lpdiaf = get_cur_lpdiaf(dialog);
    LVITEMW item;
    int i, j;

    /* Clean the listview */
    SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_DELETEALLITEMS, 0, 0);

    /* Add each object */
    for (i=0; i < device->nobjects; i++)
    {
        int action = -1;

        item.mask = LVIF_TEXT | LVIF_PARAM;
        item.iItem = i;
        item.iSubItem = 0;
        item.pszText = device->ddo[i].tszName;
        item.cchTextMax = lstrlenW(item.pszText);

        /* Add the item */
        SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_INSERTITEMW, 0, (LPARAM) &item);

        /* Search for an assigned action  for this device */
        for (j=0; j < lpdiaf->dwNumActions; j++)
        {
            if (IsEqualGUID(&lpdiaf->rgoAction[j].guidInstance, &device->ddi.guidInstance) &&
                lpdiaf->rgoAction[j].dwObjID == device->ddo[i].dwType)
            {
                action = j;
                break;
            }
        }

        lv_set_action(dialog, i, action, lpdiaf);
    }
}

static void show_suitable_actions(HWND dialog)
{
    DeviceData *device = get_cur_device(dialog);
    LPDIACTIONFORMATW lpdiaf = get_cur_lpdiaf(dialog);
    int i, added = 0;
    int obj = lv_get_cur_item(dialog);

    if (obj < 0) return;

    SendDlgItemMessageW(dialog, IDC_ACTIONLIST, LB_RESETCONTENT, 0, 0);

    for (i=0; i < lpdiaf->dwNumActions; i++)
    {
        /* Skip keyboard actions for non keyboards */
        if (GET_DIDEVICE_TYPE(device->ddi.dwDevType) != DI8DEVTYPE_KEYBOARD &&
            (lpdiaf->rgoAction[i].dwSemantic & DIKEYBOARD_MASK) == DIKEYBOARD_MASK) continue;

        /* Skip mouse actions for non mouses */
        if (GET_DIDEVICE_TYPE(device->ddi.dwDevType) != DI8DEVTYPE_MOUSE &&
            (lpdiaf->rgoAction[i].dwSemantic & DIMOUSE_MASK) == DIMOUSE_MASK) continue;

        /* Add action string and index in the action format to the list entry */
        if (DIDFT_GETINSTANCE(lpdiaf->rgoAction[i].dwSemantic) & DIDFT_GETTYPE(device->ddo[obj].dwType))
        {
            SendDlgItemMessageW(dialog, IDC_ACTIONLIST, LB_ADDSTRING, 0, (LPARAM)lpdiaf->rgoAction[i].u.lptszActionName);
            SendDlgItemMessageW(dialog, IDC_ACTIONLIST, LB_SETITEMDATA, added, (LPARAM) i);
            added++;
        }
    }
}

static void assign_action(HWND dialog)
{
    DeviceData *device = get_cur_device(dialog);
    LPDIACTIONFORMATW lpdiaf = get_cur_lpdiaf(dialog);
    LVFINDINFOW lvFind;
    int sel = SendDlgItemMessageW(dialog, IDC_ACTIONLIST, LB_GETCURSEL, 0, 0);
    int action = SendDlgItemMessageW(dialog, IDC_ACTIONLIST, LB_GETITEMDATA, sel, 0);
    int obj = lv_get_cur_item(dialog);
    int old_action = lv_get_item_data(dialog, obj);
    int used_obj;

    DIDEVICEOBJECTINSTANCEW ddo = device->ddo[obj];

    if (old_action == action) return;

    /* Clear old action */
    if (old_action != -1)
    {
        lpdiaf->rgoAction[old_action].dwObjID = 0;
        lpdiaf->rgoAction[old_action].guidInstance = GUID_NULL;
        lpdiaf->rgoAction[old_action].dwHow = DIAH_UNMAPPED;
    }

    /* Find if action text is already set for other object and unset it */
    lvFind.flags = LVFI_PARAM;
    lvFind.lParam = action;

    used_obj = SendDlgItemMessageW(dialog, IDC_DEVICEOBJECTSLIST, LVM_FINDITEMW, -1, (LPARAM) &lvFind);

    lv_set_action(dialog, used_obj, -1, lpdiaf);

    /* Set new action */
    lpdiaf->rgoAction[action].dwObjID = ddo.dwType;
    lpdiaf->rgoAction[action].guidInstance = device->ddi.guidInstance;
    lpdiaf->rgoAction[action].dwHow = DIAH_USERCONFIG;

    /* Set new action in the list */
    lv_set_action(dialog, obj, action, lpdiaf);
}

static void copy_actions(LPDIACTIONFORMATW to, LPDIACTIONFORMATW from)
{
    DWORD i;
    for (i=0; i < from->dwNumActions; i++)
    {
        to->rgoAction[i].guidInstance = from->rgoAction[i].guidInstance;
        to->rgoAction[i].dwObjID = from->rgoAction[i].dwObjID;
        to->rgoAction[i].dwHow = from->rgoAction[i].dwHow;
        to->rgoAction[i].u.lptszActionName = from->rgoAction[i].u.lptszActionName;
    }
}

static void reset_actions(HWND dialog)
{
    ConfigureDevicesData *data = (ConfigureDevicesData*) GetWindowLongPtrW(dialog, DWLP_USER);
    LPDIACTIONFORMATW to = data->lpdiaf, from = data->original_lpdiaf;

    copy_actions(to, from);
}

static INT_PTR CALLBACK ConfigureDevicesDlgProc(HWND dialog, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        case WM_INITDIALOG:
        {
            ConfigureDevicesData *data = (ConfigureDevicesData*) lParam;

            /* Initialize action format and enumerate devices */
            init_devices(dialog, data->lpDI, &data->devices_data, data->lpdiaf);

            /* Store information in the window */
            SetWindowLongPtrW(dialog, DWLP_USER, (LONG_PTR) data);

            init_listview_columns(dialog);

            /* Create a backup action format for CANCEL and RESET operations */
            data->original_lpdiaf = HeapAlloc(GetProcessHeap(), 0, sizeof(*data->original_lpdiaf));
            data->original_lpdiaf->dwNumActions = data->lpdiaf->dwNumActions;
            data->original_lpdiaf->rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*data->lpdiaf->dwNumActions);
            copy_actions(data->original_lpdiaf, data->lpdiaf);

            /* Select the first device and show its actions */
            SendDlgItemMessageW(dialog, IDC_CONTROLLERCOMBO, CB_SETCURSEL, 0, 0);
            fill_device_object_list(dialog);

            break;
        }

        case WM_NOTIFY:

            switch (((LPNMHDR)lParam)->code)
            {
                case LVN_ITEMCHANGED:
                    show_suitable_actions(dialog);
                    break;
            }
            break;


        case WM_COMMAND:

            switch(LOWORD(wParam))
            {

                case IDC_ACTIONLIST:

                    switch (HIWORD(wParam))
                    {
                        case LBN_DBLCLK:
                            /* Ignore this if app did not ask for editing */
                            if (dialog_display_only(dialog)) break;

                            assign_action(dialog);
                            break;
                    }
                    break;

                case IDC_CONTROLLERCOMBO:

                    switch (HIWORD(wParam))
                    {
                        case CBN_SELCHANGE:
                            fill_device_object_list(dialog);
                            break;
                    }
                    break;

                case IDOK:
                    EndDialog(dialog, 0);
                    destroy_data(dialog);
                    break;

                case IDCANCEL:
                    reset_actions(dialog);
                    EndDialog(dialog, 0);
                    destroy_data(dialog);
                    break;

                case IDC_RESET:
                    reset_actions(dialog);
                    fill_device_object_list(dialog);
                    break;
            }
        break;
    }

    return FALSE;
}

HRESULT _configure_devices(IDirectInput8W *iface,
                           LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
                           LPDICONFIGUREDEVICESPARAMSW lpdiCDParams,
                           DWORD dwFlags,
                           LPVOID pvRefData
)
{
    ConfigureDevicesData data;
    data.lpDI = iface;
    data.lpdiaf = lpdiCDParams->lprgFormats;
    data.display_only = !(dwFlags & DICD_EDIT);

    InitCommonControls();

    DialogBoxParamW(GetModuleHandleA("dinput.dll"), (LPCWSTR) MAKEINTRESOURCE(IDD_CONFIGUREDEVICES), lpdiCDParams->hwnd, ConfigureDevicesDlgProc, (LPARAM) &data);

    return DI_OK;
}
