/*
 * Implementation of event-related interfaces for IE Web Browser control:
 *
 *  - IConnectionPointContainer
 *  - IConnectionPoint
 *
 * 2001 John R. Sheets (for CodeWeavers)
 *
 * Copyright (c) 2003 TransGaming Technologies
 * david@transgaming.com
 */

#include <string.h>
#include "wine/debug.h"
#include "shdocvw.h"

WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);

static HRESULT SHDOCVW_CreateWBConnectionPoint(IUnknown *pOuter, REFIID riid, LPVOID *ppobj);

/**********************************************************************
 * Implement the IConnectionPointContainer interface
 */

static HRESULT WINAPI WBCPC_QueryInterface(LPCONNECTIONPOINTCONTAINER iface,
                                           REFIID riid, LPVOID *ppobj)
{
    ICOM_THIS_MULTI(IWebBrowserImpl, lpVtbl_CPC, iface);

    TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppobj);
    return IWebBrowser_QueryInterface((LPWEBBROWSER) This, riid, ppobj);
}

static ULONG WINAPI WBCPC_AddRef(LPCONNECTIONPOINTCONTAINER iface)
{
    ICOM_THIS_MULTI(IWebBrowserImpl, lpVtbl_CPC, iface);
    TRACE("(%p)->()\n", iface);
    return IWebBrowser_AddRef((LPWEBBROWSER) This);
}

static ULONG WINAPI WBCPC_Release(LPCONNECTIONPOINTCONTAINER iface)
{
    ICOM_THIS_MULTI(IWebBrowserImpl, lpVtbl_CPC, iface);
    TRACE("(%p)->()\n", iface);
    return IWebBrowser_Release((LPWEBBROWSER) This);
}

/* Get a list of connection points inside this container. */
static HRESULT WINAPI WBCPC_EnumConnectionPoints(LPCONNECTIONPOINTCONTAINER iface,
                                                 LPENUMCONNECTIONPOINTS *ppEnum)
{
    /*ICOM_THIS_MULTI(IWebBrowserImpl, lpVtbl_CPC, iface)*/
    FIXME("(%p)->(...): stub\n", iface);
    return S_OK;
}

/* Retrieve the connection point in this container associated with the
 * riid interface.  When events occur in the control, the control can
 * call backwards into its embedding site, through these interfaces.
 */
static HRESULT WINAPI WBCPC_FindConnectionPoint(LPCONNECTIONPOINTCONTAINER iface,
                                                REFIID riid, LPCONNECTIONPOINT *ppCP)
{
    /*ICOM_THIS_MULTI(IWebBrowserImpl, lpVtbl_CPC, iface);*/
    FIXME("(%p)->(%s, %p): semi-stub\n", iface, debugstr_guid(riid), *ppCP);

    /* For now, return the same IConnectionPoint object for both
     * event interface requests.
     */
    /* FIXME : ugly hack see connection point query interface */
    return SHDOCVW_CreateWBConnectionPoint(NULL, riid, (void**)ppCP);
}

/**********************************************************************
 * IConnectionPointContainer virtual function table for WebBrowser class
 */

ICOM_VTABLE(IConnectionPointContainer) WBCPC_Vtbl =
{
    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
    WBCPC_QueryInterface,
    WBCPC_AddRef,
    WBCPC_Release,
    WBCPC_EnumConnectionPoints,
    WBCPC_FindConnectionPoint
};


/**********************************************************************
 * Implement the IConnectionPoint interface
 */

static HRESULT WINAPI WBCP_QueryInterface(LPCONNECTIONPOINT iface,
                                          REFIID riid, LPVOID *ppobj)
{
    ICOM_THIS(IConnectionPointImpl, iface);

    TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppobj);

    if (IsEqualGUID(&IID_IUnknown, riid) ||
        IsEqualGUID(&IID_IConnectionPoint, riid))
    {
        This->ref++;
        *ppobj = This;
        return S_OK;
    }
    /* FIXME: ugly hack - this was in FindConnectionPoint before */
    else if (IsEqualGUID(&IID_INotifyDBEvents, riid) ||
             IsEqualGUID(&IID_IPropertyNotifySink, riid) ||
             /* ah stuff it for now! - steam wants to use
              * DIID_DWebBrowserEvents2 and I can't be bothered fixing up the headers*/
             1)
    {
        FIXME("Returning an invalid interface to satisfy something!\n");
        This->ref++;
        *ppobj = This;
        return S_OK;
    }
    else
    {
        FIXME("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppobj);
        return E_NOINTERFACE;
    }
}

static ULONG WINAPI WBCP_AddRef(LPCONNECTIONPOINT iface)
{
    ICOM_THIS(IConnectionPointImpl, iface);
    TRACE("(%p)->()\n", iface);
    return ++This->ref;
}

static ULONG WINAPI WBCP_Release(LPCONNECTIONPOINT iface)
{
    ICOM_THIS(IConnectionPointImpl, iface);
    TRACE("(%p)->()\n", iface);
    if (--This->ref) return This->ref;

    HeapFree(GetProcessHeap(), 0, This);
    return 0;
}

static HRESULT WINAPI WBCP_GetConnectionInterface(LPCONNECTIONPOINT iface, IID* pIId)
{
    /*ICOM_THIS(IConnectionPointImpl, iface);*/
    FIXME("(%p)->(...): stub\n", iface);
    return S_OK;
}

/* Get this connection point's owning container */
static HRESULT WINAPI
WBCP_GetConnectionPointContainer(LPCONNECTIONPOINT iface,
                                 LPCONNECTIONPOINTCONTAINER *ppCPC)
{
    /*ICOM_THIS(IConnectionPointImpl, iface);*/
    FIXME("(%p)->(...): stub\n", iface);
    return S_OK;
}

/* Connect the pUnkSink event-handling implementation (in the control site)
 * to this connection point.  Return a handle to this connection in
 * pdwCookie (for later use in Unadvise()).
 */
static HRESULT WINAPI WBCP_Advise(LPCONNECTIONPOINT iface,
                                  LPUNKNOWN pUnkSink, DWORD *pdwCookie)
{
    ICOM_THIS(IConnectionPointImpl, iface);
    FIXME("(%p)->(...): stub\n", iface);

    *pdwCookie = ++This->dwCookieCount;

    TRACE ("Returning cookie = %ld\n", *pdwCookie);

    return S_OK;
}

/* Disconnect this implementation from the connection point. */
static HRESULT WINAPI WBCP_Unadvise(LPCONNECTIONPOINT iface,
                                    DWORD dwCookie)
{
    /*ICOM_THIS(IConnectionPointImpl, iface);*/
    FIXME("(%p)->(%ld)\n", iface, dwCookie);
    return S_OK;
}

/* Get a list of connections in this connection point. */
static HRESULT WINAPI WBCP_EnumConnections(LPCONNECTIONPOINT iface,
                                           LPENUMCONNECTIONS *ppEnum)
{
    /*ICOM_THIS(IConnectionPointImpl, iface);*/
    FIXME("(%p)->(...): stub\n", iface);
    return S_OK;
}

/**********************************************************************
 * IConnectionPoint virtual function table for WebBrowser class
 */

static ICOM_VTABLE(IConnectionPoint) WBCP_Vtbl =
{
    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
    WBCP_QueryInterface,
    WBCP_AddRef,
    WBCP_Release,
    WBCP_GetConnectionInterface,
    WBCP_GetConnectionPointContainer,
    WBCP_Advise,
    WBCP_Unadvise,
    WBCP_EnumConnections
};

/* HACK : not really sure where this should be created! 
 * used by COnnectionPointContainer */
static HRESULT SHDOCVW_CreateWBConnectionPoint(IUnknown *pOuter, REFIID riid, LPVOID *ppobj)
{
    IConnectionPointImpl *ipCP;
    HRESULT hr;
    TRACE("()\n");

    ipCP = (IConnectionPointImpl *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
                                         sizeof(IConnectionPointImpl));
    if (ipCP == NULL) return E_OUTOFMEMORY;
    ICOM_VTBL(ipCP) = &WBCP_Vtbl;

    IConnectionPoint_AddRef((IConnectionPoint *)ipCP);
    hr = IConnectionPoint_QueryInterface((IConnectionPoint *)ipCP, riid, ppobj);
    IConnectionPoint_Release((IConnectionPoint *)ipCP);

    if (SUCCEEDED(hr))
        return S_OK;
    else
        return E_NOINTERFACE;
}


