/*
 * 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/debug.h"
#include "wine/unicode.h"
#include "objbase.h"
#include "dinput_private.h"
#include "device_private.h"
#include "resource.h"

WINE_DEFAULT_DEBUG_CHANNEL(dinput);

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 = (DeviceData*) 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)
{
    int 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;
}
