/*
 *	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 should 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 void set_buffer(LPWSTR *buffer, LPCWSTR string)
{
    static 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);
            if (This->dwFlags & PROGDLG_NOMINIMIZE)
                SetWindowLongW(hwnd, GWL_STYLE, GetWindowLongW(hwnd, GWL_STYLE) & (~WS_MINIMIZEBOX));

            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;
}

static void ProgressDialog_Destructor(ProgressDialog *This)
{
    TRACE("destroying %p\n", This);
    if (This->hwnd)
        end_dialog(This);
    heap_free(This->lines[0]);
    heap_free(This->lines[1]);
    heap_free(This->lines[2]);
    heap_free(This->cancelMsg);
    heap_free(This->title);
    heap_free(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");

    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);

    CloseHandle(hThread);
    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, 0x%s, 0x%s)\n", This, wine_dbgstr_longlong(ullCompleted), wine_dbgstr_longlong(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
};

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

    This = heap_alloc_zero(sizeof(ProgressDialog));
    if (This == NULL)
        return E_OUTOFMEMORY;

    This->vtbl = &ProgressDialogVtbl;
    This->refCount = 1;
    InitializeCriticalSection(&This->cs);

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