/*
 * Copyright 2005-2006 Jacek Caban for CodeWeavers
 *
 * 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 "wine/debug.h"
#include "shdocvw.h"
#include "hlink.h"
#include "exdispid.h"

WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);

static ATOM doc_view_atom = 0;

static void navigate_complete(DocHost *This)
{
    IDispatch *disp = NULL;
    DISPPARAMS dispparams;
    VARIANTARG params[2];
    VARIANT url;
    HRESULT hres;

    hres = IUnknown_QueryInterface(This->document, &IID_IDispatch, (void**)&disp);
    if(FAILED(hres))
        FIXME("Could not get IDispatch interface\n");

    dispparams.cArgs = 2;
    dispparams.cNamedArgs = 0;
    dispparams.rgdispidNamedArgs = NULL;
    dispparams.rgvarg = params;

    V_VT(params) = (VT_BYREF|VT_VARIANT);
    V_BYREF(params) = &url;

    V_VT(params+1) = VT_DISPATCH;
    V_DISPATCH(params+1) = disp;

    V_VT(&url) = VT_BSTR;
    V_BSTR(&url) = SysAllocString(This->url);

    call_sink(This->cps.wbe2, DISPID_NAVIGATECOMPLETE2, &dispparams);
    call_sink(This->cps.wbe2, DISPID_DOCUMENTCOMPLETE, &dispparams);

    SysFreeString(V_BSTR(&url));
    if(disp)
        IDispatch_Release(disp);
}

static LRESULT navigate2(DocHost *This)
{
    IHlinkTarget *hlink;
    HRESULT hres;

    TRACE("(%p)\n", This);

    if(!This->document) {
        WARN("document == NULL\n");
        return 0;
    }

    hres = IUnknown_QueryInterface(This->document, &IID_IHlinkTarget, (void**)&hlink);
    if(FAILED(hres)) {
        FIXME("Could not get IHlinkTarget interface\n");
        return 0;
    }

    hres = IHlinkTarget_Navigate(hlink, 0, NULL);
    IHlinkTarget_Release(hlink);
    if(FAILED(hres)) {
        FIXME("Navigate failed\n");
        return 0;
    }

    navigate_complete(This);

    return 0;
}

static LRESULT resize_document(DocHost *This, LONG width, LONG height)
{
    RECT rect = {0, 0, width, height};

    TRACE("(%p)->(%d %d)\n", This, width, height);

    if(This->view)
        IOleDocumentView_SetRect(This->view, &rect);

    return 0;
}

static LRESULT WINAPI doc_view_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    DocHost *This;

    static const WCHAR wszTHIS[] = {'T','H','I','S',0};

    if(msg == WM_CREATE) {
        This = *(DocHost**)lParam;
        SetPropW(hwnd, wszTHIS, This);
    }else {
        This = GetPropW(hwnd, wszTHIS);
    }

    switch(msg) {
    case WM_SIZE:
        return resize_document(This, LOWORD(lParam), HIWORD(lParam));
    case WB_WM_NAVIGATE2:
        return navigate2(This);
    }

    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

void create_doc_view_hwnd(DocHost *This)
{
    RECT rect;

    static const WCHAR wszShell_DocObject_View[] =
        {'S','h','e','l','l',' ','D','o','c','O','b','j','e','c','t',' ','V','i','e','w',0};

    if(!doc_view_atom) {
        static WNDCLASSEXW wndclass = {
            sizeof(wndclass),
            CS_PARENTDC,
            doc_view_proc,
            0, 0 /* native uses 4*/, NULL, NULL, NULL,
            (HBRUSH)COLOR_WINDOWFRAME, NULL,
            wszShell_DocObject_View,
            NULL
        };

        wndclass.hInstance = shdocvw_hinstance;

        doc_view_atom = RegisterClassExW(&wndclass);
    }

    GetClientRect(This->frame_hwnd, &rect); /* FIXME */
    This->hwnd = CreateWindowExW(0, wszShell_DocObject_View,
         wszShell_DocObject_View,
         WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP,
         rect.left, rect.top, rect.right, rect.bottom, This->frame_hwnd,
         NULL, shdocvw_hinstance, This);
}

void deactivate_document(DocHost *This)
{
    IOleInPlaceObjectWindowless *winobj;
    IOleObject *oleobj = NULL;
    IHlinkTarget *hlink = NULL;
    HRESULT hres;

    if(This->view)
        IOleDocumentView_UIActivate(This->view, FALSE);

    hres = IUnknown_QueryInterface(This->document, &IID_IOleInPlaceObjectWindowless,
                                   (void**)&winobj);
    if(SUCCEEDED(hres)) {
        IOleInPlaceObjectWindowless_InPlaceDeactivate(winobj);
        IOleInPlaceObjectWindowless_Release(winobj);
    }

    if(This->view) {
        IOleDocumentView_Show(This->view, FALSE);
        IOleDocumentView_CloseView(This->view, 0);
        IOleDocumentView_SetInPlaceSite(This->view, NULL);
        IOleDocumentView_Release(This->view);
        This->view = NULL;
    }

    hres = IUnknown_QueryInterface(This->document, &IID_IOleObject, (void**)&oleobj);
    if(SUCCEEDED(hres))
        IOleObject_Close(oleobj, OLECLOSE_NOSAVE);

    hres = IUnknown_QueryInterface(This->document, &IID_IHlinkTarget, (void**)&hlink);
    if(SUCCEEDED(hres)) {
        IHlinkTarget_SetBrowseContext(hlink, NULL);
        IHlinkTarget_Release(hlink);
    }

    if(oleobj) {
        IOleClientSite *client_site = NULL;

        IOleObject_GetClientSite(oleobj, &client_site);
        if(client_site) {
            if(client_site == CLIENTSITE(This))
                IOleObject_SetClientSite(oleobj, NULL);
            IOleClientSite_Release(client_site);
        }

        IOleObject_Release(oleobj);
    }

    IUnknown_Release(This->document);
    This->document = NULL;
}

#define OLECMD_THIS(iface) DEFINE_THIS(DocHost, OleCommandTarget, iface)

static HRESULT WINAPI ClOleCommandTarget_QueryInterface(IOleCommandTarget *iface,
        REFIID riid, void **ppv)
{
    DocHost *This = OLECMD_THIS(iface);
    return IOleClientSite_QueryInterface(CLIENTSITE(This), riid, ppv);
}

static ULONG WINAPI ClOleCommandTarget_AddRef(IOleCommandTarget *iface)
{
    DocHost *This = OLECMD_THIS(iface);
    return IOleClientSite_AddRef(CLIENTSITE(This));
}

static ULONG WINAPI ClOleCommandTarget_Release(IOleCommandTarget *iface)
{
    DocHost *This = OLECMD_THIS(iface);
    return IOleClientSite_Release(CLIENTSITE(This));
}

static HRESULT WINAPI ClOleCommandTarget_QueryStatus(IOleCommandTarget *iface,
        const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
{
    DocHost *This = OLECMD_THIS(iface);
    FIXME("(%p)->(%s %u %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds,
          pCmdText);
    return E_NOTIMPL;
}

static HRESULT WINAPI ClOleCommandTarget_Exec(IOleCommandTarget *iface,
        const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn,
        VARIANT *pvaOut)
{
    DocHost *This = OLECMD_THIS(iface);
    FIXME("(%p)->(%s %d %d %p %p)\n", This, debugstr_guid(pguidCmdGroup), nCmdID,
          nCmdexecopt, pvaIn, pvaOut);
    return E_NOTIMPL;
}

#undef OLECMD_THIS

static const IOleCommandTargetVtbl OleCommandTargetVtbl = {
    ClOleCommandTarget_QueryInterface,
    ClOleCommandTarget_AddRef,
    ClOleCommandTarget_Release,
    ClOleCommandTarget_QueryStatus,
    ClOleCommandTarget_Exec
};

#define DOCHOSTUI_THIS(iface) DEFINE_THIS(DocHost, DocHostUIHandler, iface)

static HRESULT WINAPI DocHostUIHandler_QueryInterface(IDocHostUIHandler2 *iface,
                                                      REFIID riid, void **ppv)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    return IOleClientSite_QueryInterface(CLIENTSITE(This), riid, ppv);
}

static ULONG WINAPI DocHostUIHandler_AddRef(IDocHostUIHandler2 *iface)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    return IOleClientSite_AddRef(CLIENTSITE(This));
}

static ULONG WINAPI DocHostUIHandler_Release(IDocHostUIHandler2 *iface)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    return IOleClientSite_Release(CLIENTSITE(This));
}

static HRESULT WINAPI DocHostUIHandler_ShowContextMenu(IDocHostUIHandler2 *iface,
         DWORD dwID, POINT *ppt, IUnknown *pcmdtReserved, IDispatch *pdispReserved)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    HRESULT hres;

    TRACE("(%p)->(%d %p %p %p)\n", This, dwID, ppt, pcmdtReserved, pdispReserved);

    if(This->hostui) {
        hres = IDocHostUIHandler_ShowContextMenu(This->hostui, dwID, ppt, pcmdtReserved,
                                                 pdispReserved);
        if(hres == S_OK)
            return S_OK;
    }

    FIXME("default action not implemented\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI DocHostUIHandler_GetHostInfo(IDocHostUIHandler2 *iface,
        DOCHOSTUIINFO *pInfo)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    HRESULT hres;

    TRACE("(%p)->(%p)\n", This, pInfo);

    if(This->hostui) {
        hres = IDocHostUIHandler_GetHostInfo(This->hostui, pInfo);
        if(SUCCEEDED(hres))
            return hres;
    }

    pInfo->dwFlags = DOCHOSTUIFLAG_DISABLE_HELP_MENU | DOCHOSTUIFLAG_OPENNEWWIN
        | DOCHOSTUIFLAG_URL_ENCODING_ENABLE_UTF8 | DOCHOSTUIFLAG_ENABLE_INPLACE_NAVIGATION
        | DOCHOSTUIFLAG_IME_ENABLE_RECONVERSION;
    return S_OK;
}

static HRESULT WINAPI DocHostUIHandler_ShowUI(IDocHostUIHandler2 *iface, DWORD dwID,
        IOleInPlaceActiveObject *pActiveObject, IOleCommandTarget *pCommandTarget,
        IOleInPlaceFrame *pFrame, IOleInPlaceUIWindow *pDoc)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    FIXME("(%p)->(%d %p %p %p %p)\n", This, dwID, pActiveObject, pCommandTarget,
          pFrame, pDoc);
    return E_NOTIMPL;
}

static HRESULT WINAPI DocHostUIHandler_HideUI(IDocHostUIHandler2 *iface)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    FIXME("(%p)\n", This);
    return E_NOTIMPL;
}

static HRESULT WINAPI DocHostUIHandler_UpdateUI(IDocHostUIHandler2 *iface)
{
    DocHost *This = DOCHOSTUI_THIS(iface);

    TRACE("(%p)\n", This);

    if(!This->hostui)
        return S_FALSE;

    return IDocHostUIHandler_UpdateUI(This->hostui);
}

static HRESULT WINAPI DocHostUIHandler_EnableModeless(IDocHostUIHandler2 *iface,
                                                      BOOL fEnable)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    FIXME("(%p)->(%x)\n", This, fEnable);
    return E_NOTIMPL;
}

static HRESULT WINAPI DocHostUIHandler_OnDocWindowActivate(IDocHostUIHandler2 *iface,
                                                           BOOL fActivate)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    FIXME("(%p)->(%x)\n", This, fActivate);
    return E_NOTIMPL;
}

static HRESULT WINAPI DocHostUIHandler_OnFrameWindowActivate(IDocHostUIHandler2 *iface,
                                                             BOOL fActivate)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    FIXME("(%p)->(%x)\n", This, fActivate);
    return E_NOTIMPL;
}

static HRESULT WINAPI DocHostUIHandler_ResizeBorder(IDocHostUIHandler2 *iface,
        LPCRECT prcBorder, IOleInPlaceUIWindow *pUIWindow, BOOL fRameWindow)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    FIXME("(%p)->(%p %p %X)\n", This, prcBorder, pUIWindow, fRameWindow);
    return E_NOTIMPL;
}

static HRESULT WINAPI DocHostUIHandler_TranslateAccelerator(IDocHostUIHandler2 *iface,
        LPMSG lpMsg, const GUID *pguidCmdGroup, DWORD nCmdID)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    FIXME("(%p)->(%p %p %d)\n", This, lpMsg, pguidCmdGroup, nCmdID);
    return E_NOTIMPL;
}

static HRESULT WINAPI DocHostUIHandler_GetOptionKeyPath(IDocHostUIHandler2 *iface,
        LPOLESTR *pchKey, DWORD dw)
{
    DocHost *This = DOCHOSTUI_THIS(iface);

    TRACE("(%p)->(%p %d)\n", This, pchKey, dw);

    if(This->hostui)
        return IDocHostUIHandler_GetOptionKeyPath(This->hostui, pchKey, dw);

    return S_OK;
}

static HRESULT WINAPI DocHostUIHandler_GetDropTarget(IDocHostUIHandler2 *iface,
        IDropTarget *pDropTarget, IDropTarget **ppDropTarget)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    FIXME("(%p)\n", This);
    return E_NOTIMPL;
}

static HRESULT WINAPI DocHostUIHandler_GetExternal(IDocHostUIHandler2 *iface,
        IDispatch **ppDispatch)
{
    DocHost *This = DOCHOSTUI_THIS(iface);

    TRACE("(%p)->(%p)\n", This, ppDispatch);

    if(This->hostui)
        return IDocHostUIHandler_GetExternal(This->hostui, ppDispatch);

    FIXME("default action not implemented\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI DocHostUIHandler_TranslateUrl(IDocHostUIHandler2 *iface,
        DWORD dwTranslate, OLECHAR *pchURLIn, OLECHAR **ppchURLOut)
{
    DocHost *This = DOCHOSTUI_THIS(iface);

    TRACE("(%p)->(%d %s %p)\n", This, dwTranslate, debugstr_w(pchURLIn), ppchURLOut);

    if(This->hostui)
        return IDocHostUIHandler_TranslateUrl(This->hostui, dwTranslate,
                                              pchURLIn, ppchURLOut);

    return S_FALSE;
}

static HRESULT WINAPI DocHostUIHandler_FilterDataObject(IDocHostUIHandler2 *iface,
        IDataObject *pDO, IDataObject **ppDORet)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    FIXME("(%p)->(%p %p)\n", This, pDO, ppDORet);
    return E_NOTIMPL;
}

static HRESULT WINAPI DocHostUIHandler_GetOverrideKeyPath(IDocHostUIHandler2 *iface,
        LPOLESTR *pchKey, DWORD dw)
{
    DocHost *This = DOCHOSTUI_THIS(iface);
    IDocHostUIHandler2 *handler;
    HRESULT hres;

    TRACE("(%p)->(%p %d)\n", This, pchKey, dw);

    if(!This->hostui)
        return S_OK;

    hres = IDocHostUIHandler_QueryInterface(This->hostui, &IID_IDocHostUIHandler2,
                                            (void**)&handler);
    if(SUCCEEDED(hres)) {
        hres = IDocHostUIHandler2_GetOverrideKeyPath(handler, pchKey, dw);
        IDocHostUIHandler2_Release(handler);
        return hres;
    }

    return S_OK;
}

#undef DOCHOSTUI_THIS

static const IDocHostUIHandler2Vtbl DocHostUIHandler2Vtbl = {
    DocHostUIHandler_QueryInterface,
    DocHostUIHandler_AddRef,
    DocHostUIHandler_Release,
    DocHostUIHandler_ShowContextMenu,
    DocHostUIHandler_GetHostInfo,
    DocHostUIHandler_ShowUI,
    DocHostUIHandler_HideUI,
    DocHostUIHandler_UpdateUI,
    DocHostUIHandler_EnableModeless,
    DocHostUIHandler_OnDocWindowActivate,
    DocHostUIHandler_OnFrameWindowActivate,
    DocHostUIHandler_ResizeBorder,
    DocHostUIHandler_TranslateAccelerator,
    DocHostUIHandler_GetOptionKeyPath,
    DocHostUIHandler_GetDropTarget,
    DocHostUIHandler_GetExternal,
    DocHostUIHandler_TranslateUrl,
    DocHostUIHandler_FilterDataObject,
    DocHostUIHandler_GetOverrideKeyPath
};

void DocHost_Init(DocHost *This, IDispatch *disp)
{
    This->lpDocHostUIHandlerVtbl = &DocHostUIHandler2Vtbl;
    This->lpOleCommandTargetVtbl = &OleCommandTargetVtbl;

    This->disp = disp;

    This->client_disp = NULL;

    This->document = NULL;
    This->hostui = NULL;
    This->frame = NULL;

    This->hwnd = NULL;
    This->frame_hwnd = NULL;
    This->url = NULL;

    This->silent = VARIANT_FALSE;
    This->offline = VARIANT_FALSE;

    DocHost_ClientSite_Init(This);
    DocHost_Frame_Init(This);

    ConnectionPointContainer_Init(&This->cps, (IUnknown*)disp);
}

void DocHost_Release(DocHost *This)
{
    if(This->client_disp)
        IDispatch_Release(This->client_disp);
    if(This->frame)
        IOleInPlaceFrame_Release(This->frame);

    DocHost_ClientSite_Release(This);

    ConnectionPointContainer_Destroy(&This->cps);

    SysFreeString(This->url);
}
