#include "Controls.h"
#include "commdlg.h"
#include "CommCtrl.h"
#include "FileUtilities.h"
#include "History.h"

#define CHECKBOX_VALUE_SIZE 257

HWND MakeButton(
    HWND hWindow,
    LPCWSTR name,
    int x,
    int y,
    int width,
    int height
) {
    HWND hwndButton = CreateWindow(
        L"button",  // Predefined class; Unicode assumed 
        name,      // Button text 
        WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,  // Styles 
        x,         // x 
        y,         // y 
        width,        // width
        height,        // height
        hWindow,     // Parent window
        NULL,       // No menu
        (HINSTANCE)GetWindowLongPtr(hWindow, GWLP_HINSTANCE),
        NULL);      // Pointer not needed

    return hwndButton;
}

HWND MakeFilenameTextBox(
    HWND hWindow,
    int x,
    int y,
    int width,
    int height
) {
    HWND hTextbox = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        TEXT("Edit"),
        TEXT("Click [Run] to start in BASIC, or [Browse] to load a file\r\nYou can also pick from the history entries below."),
        WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_DISABLED | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
        x,
        y,
        width,
        height,
        hWindow,
        NULL,
        NULL,
        NULL);

    return hTextbox;
}

HWND MakeZoomDropdown(
    HWND hWindow,
    int initiallySelectedIndex,
    int x,
    int y,
    int width,
    int height
) {
    HWND hZoom = CreateWindow(
        WC_COMBOBOX,
        TEXT("Zoom"),
        CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE,
        x, y, width, height,
        hWindow, NULL, NULL, NULL);
    if (!hZoom)
    {
        return hZoom;
    }

    #define NUM_VALUES_ZOOM 9
    TCHAR values[NUM_VALUES_ZOOM][CHECKBOX_VALUE_SIZE] =
    {
        TEXT("1"),
        TEXT("2"),
        TEXT("3"),
        TEXT("4"),
        TEXT("5"),
        TEXT("6"),
        TEXT("7"),
        TEXT("8"),
        TEXT("9")
    };

    TCHAR A[CHECKBOX_VALUE_SIZE];
    memset(&A, 0, sizeof(A));
    for (int k = 0; k < NUM_VALUES_ZOOM; k += 1)
    {
        wcscpy_s(A, sizeof(A) / sizeof(TCHAR), (TCHAR*)values[k]);
        // add string to combobox
        SendMessage(hZoom, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)A);
    }

    SendMessage(hZoom, CB_SETCURSEL, (WPARAM)(initiallySelectedIndex), (LPARAM)0);
    return hZoom;
}

HWND MakeDisplayModeDropdown(
    HWND hWindow,
    int initiallySelectedIndex,
    int x,
    int y,
    int width,
    int height
) {
    HWND h = CreateWindow(
        WC_COMBOBOX,
        TEXT("DisplayMode"),
        CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE,
        x, y, width, height,
        hWindow, NULL, NULL, NULL);
    if (!h)
    {
        return h;
    }

    #define NUM_VALUES_DISPLAY_MODE 3
    TCHAR values[NUM_VALUES_DISPLAY_MODE][CHECKBOX_VALUE_SIZE] =
    {
        TEXT("0 - Windowed"),
        TEXT("1 - Desktop Fullscreen"),
        TEXT("2 - Fullscreen")
    };

    TCHAR A[CHECKBOX_VALUE_SIZE];
    memset(&A, 0, sizeof(A));
    for (int k = 0; k < NUM_VALUES_DISPLAY_MODE; k += 1)
    {
        wcscpy_s(A, sizeof(A) / sizeof(TCHAR), (TCHAR*)values[k]);
        // add string to combobox
        SendMessage(h, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)A);
    }

    SendMessage(h, CB_SETCURSEL, (WPARAM)(initiallySelectedIndex), (LPARAM)0);
    return h;
}

HWND MakeTimerDropdown(
    HWND hWindow,
    int initiallySelectedIndex,
    int x,
    int y,
    int width,
    int height
) {
    HWND h = CreateWindow(
        WC_COMBOBOX,
        TEXT("Timer"),
        CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE,
        x, y, width, height,
        hWindow, NULL, NULL, NULL);
    if (!h)
    {
        return h;
    }

    #define NUM_VALUES_TIMER 2
    TCHAR values[NUM_VALUES_TIMER][CHECKBOX_VALUE_SIZE] =
    {
        TEXT("0 - QueueTimer (default, precise)"),
        TEXT("1 - SDL_Timer   (use when speeding up emulation)")
    };

    TCHAR A[CHECKBOX_VALUE_SIZE];
    memset(&A, 0, sizeof(A));
    for (int k = 0; k < NUM_VALUES_TIMER; k += 1)
    {
        wcscpy_s(A, sizeof(A) / sizeof(TCHAR), (TCHAR*)values[k]);
        // add string to combobox
        SendMessage(h, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)A);
    }

    SendMessage(h, CB_SETCURSEL, (WPARAM)(initiallySelectedIndex), (LPARAM)0);
    return h;
}

HWND MakeControllerConfigDropdown(
    WCHAR* directory,
    HWND hWindow,
    int initiallySelectedIndex,
    int x,
    int y,
    int width,
    int height
) {
    HWND h = CreateWindow(
        WC_COMBOBOX,
        TEXT("Controller Config"),
        CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE,
        x, y, width, height,
        hWindow, NULL, NULL, NULL);
    if (!h)
    {
        return h;
    }

    // read controller config files
    int numControllerConfigFiles = -1;
    WCHAR** controllerConfigFiles = file_utilities__list_files_in_directory(directory, (WCHAR*)L"*.*", &numControllerConfigFiles);

    TCHAR A[CHECKBOX_VALUE_SIZE] = L":NONE:  use internal config (kempston)";
    // add first (hardcoded) value
    SendMessage(h, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)A);

    memset(&A, 0, sizeof(A));
    for (int k = 0; k < numControllerConfigFiles; k++)
    {
        size_t stringLength = wcslen(controllerConfigFiles[k]);
        wcscpy_s(A, stringLength+1, controllerConfigFiles[k]);
        // add string to combobox
        SendMessage(h, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)A);
    }

    SendMessage(h, CB_SETCURSEL, (WPARAM)(initiallySelectedIndex), (LPARAM)0);

    for (int i = 0; i < numControllerConfigFiles; i++) {
        free(controllerConfigFiles[i]);
    }
    free(controllerConfigFiles);
    return h;
}

/// <summary>
/// Clear all entries, and then populate all entries in the history dropdown
/// </summary>
void controls_repopulate_history_dropdown(HWND h) {
    // delete all existing entries
    SendMessage(h, CB_RESETCONTENT, 0, 0);

    TCHAR A[CHECKBOX_VALUE_SIZE];
    memset(&A, 0, sizeof(A));

    int historyEntryCount;
    char** historyEntries = history_get_entries(&historyEntryCount);

    for (int k = 0; k < historyEntryCount; k++)
    {
        const char* fileNameAndExtension = file_utilities__get_file_name_and_extension(historyEntries[k]);
        if (fileNameAndExtension == NULL) {
            // fall back on absolute path if file name and extension could not be parsed
            fileNameAndExtension = historyEntries[k];
        }
        size_t stringLength = strlen(fileNameAndExtension);

        // convert ASCII to wide
        size_t convertedCount;
        mbstowcs_s(&convertedCount, A, CHECKBOX_VALUE_SIZE, fileNameAndExtension, stringLength + 1);

        // add string to combobox
        SendMessage(h, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)A);
    }

    const int initiallySelectedIndex = 0;
    SendMessage(h, CB_SETCURSEL, (WPARAM)(initiallySelectedIndex), (LPARAM)0);
}

HWND MakeHistoryDropdown(
    HWND hWindow,
    int x,
    int y,
    int width,
    int height
) {
    HWND h = CreateWindow(
        WC_COMBOBOX,
        TEXT("Controller Config"),
        CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE,
        x, y, width, height,
        hWindow, NULL, NULL, NULL);
    if (!h)
    {
        return h;
    }

    controls_repopulate_history_dropdown(h);

    return h;
}

HWND MakeCheckbox(
    HWND hWindow,
    LPCWSTR name,
    HMENU id,
    int x,
    int y,
    int width,
    int height
) {
    HWND hCheckbox = CreateWindow(TEXT("button"), name,
        WS_VISIBLE | WS_CHILD | BS_CHECKBOX | BS_LEFTTEXT,
        x, y, width, height,
        hWindow, id, NULL, NULL);

    return hCheckbox;
}

HWND MakeEditbox(
    HWND hWindow,
    LPCWSTR name,
    HMENU id,
    int x,
    int y,
    int width,
    int height
) {

    HWND hEditbox = CreateWindow(L"edit", name, WS_BORDER | WS_CHILD | WS_VISIBLE, x, y,
        width, height, hWindow, id, NULL, NULL);

    return hEditbox;
}

HWND MakeGroupbox(
    HWND hWindow,
    LPCWSTR name,
    HMENU id,
    int x,
    int y,
    int width,
    int height
) {

    HWND hGroupbox = CreateWindow(L"button", name,
        WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
        x, y, width, height, hWindow, id, NULL, NULL);

    return hGroupbox;
}

HWND MakeRendererDropdown(
    HWND hWindow,
    int initiallySelectedIndex,
    int x,
    int y,
    int width,
    int height
) {
    HWND h = CreateWindow(
        WC_COMBOBOX,
        TEXT("Renderer"),
        CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE,
        x, y, width, height,
        hWindow, NULL, NULL, NULL);
    if (!h)
    {
        return h;
    }

#define NUM_VALUES_RENDERER 2
    TCHAR values[NUM_VALUES_RENDERER][CHECKBOX_VALUE_SIZE] =
    {
        TEXT("0 - Software"),
        TEXT("1 - Accelerated")
    };

    TCHAR A[CHECKBOX_VALUE_SIZE];
    memset(&A, 0, sizeof(A));
    for (int k = 0; k < NUM_VALUES_RENDERER; k += 1)
    {
        wcscpy_s(A, sizeof(A) / sizeof(TCHAR), (TCHAR*)values[k]);
        // add string to combobox
        SendMessage(h, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)A);
    }

    SendMessage(h, CB_SETCURSEL, (WPARAM)(initiallySelectedIndex), (LPARAM)0);
    return h;
}

HWND MakeSampleRateDropdown(
    HWND hWindow,
    int initiallySelectedIndex,
    int x,
    int y,
    int width,
    int height
) {
    HWND h = CreateWindow(
        WC_COMBOBOX,
        TEXT("Sample Rate"),
        CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE,
        x, y, width, height,
        hWindow, NULL, NULL, NULL);
    if (!h)
    {
        return h;
    }

#define NUM_VALUES_SAMPLE_RATE 12
    TCHAR values[NUM_VALUES_SAMPLE_RATE][CHECKBOX_VALUE_SIZE] =
    {
        TEXT("384000 Hz    (high quality)"),
        TEXT("352800 Hz"),
        TEXT("192000 Hz"),
        TEXT("176400 Hz"),
        TEXT("96000   Hz"),
        TEXT("88200   Hz"),
        TEXT("48000   Hz    (high compatibility)"),
        TEXT("44100   Hz"),
        TEXT("22050   Hz"),
        TEXT("16000   Hz"),
        TEXT("11025   Hz"),
        TEXT("8000     Hz")
    };

    TCHAR A[CHECKBOX_VALUE_SIZE];
    memset(&A, 0, sizeof(A));
    for (int k = 0; k < NUM_VALUES_SAMPLE_RATE; k += 1)
    {
        wcscpy_s(A, sizeof(A) / sizeof(TCHAR), (TCHAR*)values[k]);
        // add string to combobox
        SendMessage(h, (UINT)CB_ADDSTRING, (WPARAM)0, (LPARAM)A);
    }

    SendMessage(h, CB_SETCURSEL, (WPARAM)(initiallySelectedIndex), (LPARAM)0);
    return h;
}
