/*
 *	Progress dialog
 *
 *	Copyright 2007	Mikolaj Zalewski
 *
 * 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
 */

#include "config.h"

#include <stdarg.h>

#define COBJMACROS

#include "wine/debug.h"
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winuser.h"
#include "shlwapi.h"
#include "winerror.h"
#include "objbase.h"

#include "shlguid.h"
#include "shlobj.h"

#include "wine/unicode.h"

#include "browseui.h"
#include "resids.h"

WINE_DEFAULT_DEBUG_CHANNEL(browseui);

#define CANCEL_MSG_LINE 2

/* Note: to avoid a deadlock we don't want to send messages to the dialog
 * with the critical section held. Instead we only mark what fields shoud be
 * updated and the dialog proc does the update */
#define UPDATE_PROGRESS         0x1
#define UPDATE_TITLE            0x2
#define UPDATE_LINE1            0x4
#define UPDATE_LINE2            (UPDATE_LINE1<<1)
#define UPDATE_LINE3            (UPDATE_LINE2<<2)


#define WM_DLG_UPDATE   (WM_APP+1)  /* set to the dialog when it should update */
#define WM_DLG_DESTROY  (WM_APP+2)  /* DestroyWindow must be called from the owning thread */

typedef struct tagProgressDialog {
    const IProgressDialogVtbl *vtbl;
    LONG refCount;
    CRITICAL_SECTION cs;
    HWND hwnd;
    DWORD dwFlags;
    DWORD dwUpdate;
    LPWSTR lines[3];
    LPWSTR cancelMsg;
    LPWSTR title;
    BOOL isCancelled;
    ULONGLONG ullCompleted;
    ULONGLONG ullTotal;
    HWND hwndDisabledParent;    /* For modal dialog: the parent that need to be re-enabled when the dialog ends */
} ProgressDialog;

static const IProgressDialogVtbl ProgressDialogVtbl;

static void set_buffer(LPWSTR *buffer, LPCWSTR string)
{
    const WCHAR empty_string = {0};
    IMalloc *malloc;
    int cb;

    if (string == NULL)
        string = empty_string;
    CoGetMalloc(1, &malloc);

    cb = (strlenW(string) + 1)*sizeof(WCHAR);
    if (*buffer == NULL || cb > IMalloc_GetSize(malloc, *buffer))
        *buffer = IMalloc_Realloc(malloc, *buffer, cb);
    memcpy(*buffer, string, cb);
}

struct create_params
{
    ProgressDialog *This;
    HANDLE hEvent;
    HWND hwndParent;
};

static LPWSTR load_string(HINSTANCE hInstance, UINT uiResourceId)
{
    WCHAR string[256];
    LPWSTR ret;

    LoadStringW(hInstance, uiResourceId, string, sizeof(string)/sizeof(string[0]));
    ret = HeapAlloc(GetProcessHeap(), 0, (strlenW(string) + 1) * sizeof(WCHAR));
    strcpyW(ret, string);
    return ret;
}

static void set_progress_marquee(ProgressDialog *This)
{
    HWND hProgress = GetDlgItem(This->hwnd, IDC_PROGRESS_BAR);
    SetWindowLongW(hProgress, GWL_STYLE,
        GetWindowLongW(hProgress, GWL_STYLE)|PBS_MARQUEE);
}

void update_dialog(ProgressDialog *This, DWORD dwUpdate)
{
    WCHAR empty[] = {0};

    if (dwUpdate & UPDATE_TITLE)
        SetWindowTextW(This->hwnd, This->title);

    if (dwUpdate & UPDATE_LINE1)
        SetDlgItemTextW(This->hwnd, IDC_TEXT_LINE, (This->isCancelled ? empty : This->lines[0]));
    if (dwUpdate & UPDATE_LINE2)
        SetDlgItemTextW(This->hwnd, IDC_TEXT_LINE+1, (This->isCancelled ? empty : This->lines[1]));
    if (dwUpdate & UPDATE_LINE3)
        SetDlgItemTextW(This->hwnd, IDC_TEXT_LINE+2, (This->isCancelled ? This->cancelMsg : This->lines[2]));

    if (dwUpdate & UPDATE_PROGRESS)
    {
        ULONGLONG ullTotal = This->ullTotal;
        ULONGLONG ullCompleted = This->ullCompleted;

        /* progress bar requires 32-bit coordinates */
        while (ullTotal >> 32)
        {
            ullTotal >>= 1;
            ullCompleted >>= 1;
        }

        SendDlgItemMessageW(This->hwnd, IDC_PROGRESS_BAR, PBM_SETRANGE32, 0, (DWORD)ullTotal);
        SendDlgItemMessageW(This->hwnd, IDC_PROGRESS_BAR, PBM_SETPOS, (DWORD)ullCompleted, 0);
    }
}

static void end_dialog(ProgressDialog *This)
{
    SendMessageW(This->hwnd, WM_DLG_DESTROY, 0, 0);
    /* native doesn't reenable the window? */
    if (This->hwndDisabledParent)
        EnableWindow(This->hwndDisabledParent, TRUE);
    This->hwnd = NULL;
}

static INT_PTR CALLBACK dialog_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    ProgressDialog *This = (ProgressDialog *)GetWindowLongPtrW(hwnd, DWLP_USER);

    switch (msg)
    {
        case WM_INITDIALOG:
        {
            struct create_params *params = (struct create_params *)lParam;

            /* Note: until we set the hEvent, the object is protected by
             * the critical section held by StartProgress */
            SetWindowLongPtrW(hwnd, DWLP_USER, (LONG_PTR)params->This);
            This = params->This;
            This->hwnd = hwnd;

            if (This->dwFlags & PROGDLG_NOPROGRESSBAR)
                ShowWindow(GetDlgItem(hwnd, IDC_PROGRESS_BAR), SW_HIDE);
            if (This->dwFlags & PROGDLG_NOCANCEL)
                ShowWindow(GetDlgItem(hwnd, IDCANCEL), SW_HIDE);
            if (This->dwFlags & PROGDLG_MARQUEEPROGRESS)
                set_progress_marquee(This);

            update_dialog(This, 0xffffffff);
            This->dwUpdate = 0;
            This->isCancelled = FALSE;
            SetEvent(params->hEvent);
            return TRUE;
        }

        case WM_DLG_UPDATE:
            EnterCriticalSection(&This->cs);
            update_dialog(This, This->dwUpdate);
            This->dwUpdate = 0;
            LeaveCriticalSection(&This->cs);
            return TRUE;

        case WM_DLG_DESTROY:
            DestroyWindow(hwnd);
            PostThreadMessageW(GetCurrentThreadId(), WM_NULL, 0, 0); /* wake up the GetMessage */
            return TRUE;

        case WM_CLOSE:
        case WM_COMMAND:
            if (msg == WM_CLOSE || wParam == IDCANCEL)
            {
                EnterCriticalSection(&This->cs);
                This->isCancelled = TRUE;

                if (!This->cancelMsg)
                    This->cancelMsg = load_string(BROWSEUI_hinstance, IDS_CANCELLING);

                set_progress_marquee(This);
                EnableWindow(GetDlgItem(This->hwnd, IDCANCEL), FALSE);
                update_dialog(This, UPDATE_LINE1|UPDATE_LINE2|UPDATE_LINE3);
                LeaveCriticalSection(&This->cs);
            }
            return TRUE;
    }
    return FALSE;
}

static DWORD WINAPI dialog_thread(LPVOID lpParameter)
{
    /* Note: until we set the hEvent in WM_INITDIALOG, the ProgressDialog object
     * is protected by the critical section held by StartProgress */
    struct create_params *params = (struct create_params *)lpParameter;
    HWND hwnd;
    MSG msg;

    hwnd = CreateDialogParamW(BROWSEUI_hinstance, MAKEINTRESOURCEW(IDD_PROGRESS_DLG),
        params->hwndParent, dialog_proc, (LPARAM)params);

    while (GetMessageW(&msg, NULL, 0, 0) > 0)
    {
        if (!IsWindow(hwnd))
            break;
        if(!IsDialogMessageW(hwnd, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
        }
    }

    return 0;
}

HRESULT WINAPI ProgressDialog_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
{
    ProgressDialog *This;
    if (pUnkOuter)
        return CLASS_E_NOAGGREGATION;

    This = CoTaskMemAlloc(sizeof(ProgressDialog));
    if (This == NULL)
        return E_OUTOFMEMORY;
    ZeroMemory(This, sizeof(*This));
    This->vtbl = &ProgressDialogVtbl;
    This->refCount = 1;
    InitializeCriticalSection(&This->cs);

    TRACE("returning %p\n", This);
    *ppOut = (IUnknown *)This;
    BROWSEUI_refCount++;
    return S_OK;
}

static void WINAPI ProgressDialog_Destructor(ProgressDialog *This)
{
    TRACE("destroying %p\n", This);
    if (This->hwnd)
        end_dialog(This);
    CoTaskMemFree(This->lines[0]);
    CoTaskMemFree(This->lines[1]);
    CoTaskMemFree(This->lines[2]);
    CoTaskMemFree(This->cancelMsg);
    CoTaskMemFree(This->title);
    CoTaskMemFree(This);
    BROWSEUI_refCount--;
}

static HRESULT WINAPI ProgressDialog_QueryInterface(IProgressDialog *iface, REFIID iid, LPVOID *ppvOut)
{
    ProgressDialog *This = (ProgressDialog *)iface;
    *ppvOut = NULL;

    if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IProgressDialog))
    {
        *ppvOut = This;
    }

    if (*ppvOut)
    {
        IUnknown_AddRef(iface);
        return S_OK;
    }

    WARN("unsupported interface: %s\n", debugstr_guid(iid));
    return E_NOINTERFACE;
}

static ULONG WINAPI ProgressDialog_AddRef(IProgressDialog *iface)
{
    ProgressDialog *This = (ProgressDialog *)iface;
    return InterlockedIncrement(&This->refCount);
}

static ULONG WINAPI ProgressDialog_Release(IProgressDialog *iface)
{
    ProgressDialog *This = (ProgressDialog *)iface;
    ULONG ret;

    ret = InterlockedDecrement(&This->refCount);
    if (ret == 0)
        ProgressDialog_Destructor(This);
    return ret;
}

static HRESULT WINAPI ProgressDialog_StartProgressDialog(IProgressDialog *iface, HWND hwndParent, IUnknown *punkEnableModeless, DWORD dwFlags, LPCVOID reserved)
{
    ProgressDialog *This = (ProgressDialog *)iface;
    struct create_params params;
    HANDLE hThread;

    TRACE("(%p, %p, %x, %p)\n", iface, punkEnableModeless, dwFlags, reserved);
    if (punkEnableModeless || reserved)
        FIXME("Reserved parameters not null (%p, %p)\n", punkEnableModeless, reserved);
    if (dwFlags & PROGDLG_AUTOTIME)
        FIXME("Flags PROGDLG_AUTOTIME not supported\n");
    if (dwFlags & PROGDLG_NOTIME)
        FIXME("Flags PROGDLG_NOTIME not supported\n");
    if (dwFlags & PROGDLG_NOMINIMIZE)
        FIXME("Flags PROGDLG_NOMINIMIZE not supported\n");

    EnterCriticalSection(&This->cs);

    if (This->hwnd)
    {
        LeaveCriticalSection(&This->cs);
        return S_OK;  /* as on XP */
    }
    This->dwFlags = dwFlags;
    params.This = This;
    params.hwndParent = hwndParent;
    params.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);

    hThread = CreateThread(NULL, 0, dialog_thread, &params, 0, NULL);
    WaitForSingleObject(params.hEvent, INFINITE);

    This->hwndDisabledParent = NULL;
    if (hwndParent && (dwFlags & PROGDLG_MODAL))
    {
        HWND hwndDisable = GetAncestor(hwndParent, GA_ROOT);
        if (EnableWindow(hwndDisable, FALSE))
            This->hwndDisabledParent = hwndDisable;
    }

    LeaveCriticalSection(&This->cs);

    return S_OK;
}

static HRESULT WINAPI ProgressDialog_StopProgressDialog(IProgressDialog *iface)
{
    ProgressDialog *This = (ProgressDialog *)iface;

    EnterCriticalSection(&This->cs);
    if (This->hwnd)
        end_dialog(This);
    LeaveCriticalSection(&This->cs);

    return S_OK;
}

static HRESULT WINAPI ProgressDialog_SetTitle(IProgressDialog *iface, LPCWSTR pwzTitle)
{
    ProgressDialog *This = (ProgressDialog *)iface;
    HWND hwnd;

    TRACE("(%p, %s)\n", This, wine_dbgstr_w(pwzTitle));

    EnterCriticalSection(&This->cs);
    set_buffer(&This->title, pwzTitle);
    This->dwUpdate |= UPDATE_TITLE;
    hwnd = This->hwnd;
    LeaveCriticalSection(&This->cs);

    if (hwnd)
        SendMessageW(hwnd, WM_DLG_UPDATE, 0, 0);

    return S_OK;
}

static HRESULT WINAPI ProgressDialog_SetAnimation(IProgressDialog *iface, HINSTANCE hInstance, UINT uiResourceId)
{
    FIXME("(%p, %p, %d) - stub\n", iface, hInstance, uiResourceId);
    return S_OK;
}

static BOOL WINAPI ProgressDialog_HasUserCancelled(IProgressDialog *iface)
{
    ProgressDialog *This = (ProgressDialog *)iface;
    return This->isCancelled;
}

static HRESULT WINAPI ProgressDialog_SetProgress64(IProgressDialog *iface, ULONGLONG ullCompleted, ULONGLONG ullTotal)
{
    ProgressDialog *This = (ProgressDialog *)iface;
    HWND hwnd;

    TRACE("(%p, %llu, %llu)\n", This, ullCompleted, ullTotal);

    EnterCriticalSection(&This->cs);
    This->ullTotal = ullTotal;
    This->ullCompleted = ullCompleted;
    This->dwUpdate |= UPDATE_PROGRESS;
    hwnd = This->hwnd;
    LeaveCriticalSection(&This->cs);

    if (hwnd)
        SendMessageW(hwnd, WM_DLG_UPDATE, 0, 0);

    return S_OK;  /* Windows sometimes returns S_FALSE */
}

static HRESULT WINAPI ProgressDialog_SetProgress(IProgressDialog *iface, DWORD dwCompleted, DWORD dwTotal)
{
    return IProgressDialog_SetProgress64(iface, dwCompleted, dwTotal);
}

static HRESULT WINAPI ProgressDialog_SetLine(IProgressDialog *iface, DWORD dwLineNum, LPCWSTR pwzLine, BOOL bPath, LPCVOID reserved)
{
    ProgressDialog *This = (ProgressDialog *)iface;
    HWND hwnd;

    TRACE("(%p, %d, %s, %d)\n", This, dwLineNum, wine_dbgstr_w(pwzLine), bPath);

    if (reserved)
        FIXME("reserved pointer not null (%p)\n", reserved);

    dwLineNum--;
    if (dwLineNum >= 3)  /* Windows seems to do something like that */
        dwLineNum = 0;

    EnterCriticalSection(&This->cs);
    set_buffer(&This->lines[dwLineNum], pwzLine);
    This->dwUpdate |= UPDATE_LINE1 << dwLineNum;
    hwnd = (This->isCancelled ? NULL : This->hwnd); /* no sense to send the message if window cancelled */
    LeaveCriticalSection(&This->cs);

    if (hwnd)
        SendMessageW(hwnd, WM_DLG_UPDATE, 0, 0);

    return S_OK;
}

static HRESULT WINAPI ProgressDialog_SetCancelMsg(IProgressDialog *iface, LPCWSTR pwzMsg, LPCVOID reserved)
{
    ProgressDialog *This = (ProgressDialog *)iface;
    HWND hwnd;

    TRACE("(%p, %s)\n", This, wine_dbgstr_w(pwzMsg));

    if (reserved)
        FIXME("reserved pointer not null (%p)\n", reserved);

    EnterCriticalSection(&This->cs);
    set_buffer(&This->cancelMsg, pwzMsg);
    This->dwUpdate |= UPDATE_LINE1 << CANCEL_MSG_LINE;
    hwnd = (This->isCancelled ? This->hwnd : NULL); /* no sense to send the message if window not cancelled */
    LeaveCriticalSection(&This->cs);

    if (hwnd)
        SendMessageW(hwnd, WM_DLG_UPDATE, 0, 0);

    return S_OK;
}

static HRESULT WINAPI ProgressDialog_Timer(IProgressDialog *iface, DWORD dwTimerAction, LPCVOID reserved)
{
    ProgressDialog *This = (ProgressDialog *)iface;

    FIXME("(%p, %d, %p) - stub\n", This, dwTimerAction, reserved);

    if (reserved)
        FIXME("Reserved field not NULL but %p\n", reserved);

    return S_OK;
}

static const IProgressDialogVtbl ProgressDialogVtbl =
{
    ProgressDialog_QueryInterface,
    ProgressDialog_AddRef,
    ProgressDialog_Release,

    ProgressDialog_StartProgressDialog,
    ProgressDialog_StopProgressDialog,
    ProgressDialog_SetTitle,
    ProgressDialog_SetAnimation,
    ProgressDialog_HasUserCancelled,
    ProgressDialog_SetProgress,
    ProgressDialog_SetProgress64,
    ProgressDialog_SetLine,
    ProgressDialog_SetCancelMsg,
    ProgressDialog_Timer
};
