/*
 * Copyright 2008 Piotr Caban
 *
 * 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
 */

#define COBJMACROS
#define NONAMELESSUNION

#include "config.h"

#include <stdarg.h>
#include <assert.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "ole2.h"
#include "msxml2.h"
#include "wininet.h"
#include "urlmon.h"
#include "winreg.h"
#include "shlwapi.h"

#include "wine/debug.h"

#include "msxml_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(msxml);

struct bsc_t {
    const struct IBindStatusCallbackVtbl *lpVtbl;

    LONG ref;

    void *obj;
    HRESULT (*onDataAvailable)(void*,char*,DWORD);

    IBinding *binding;
    IStream *memstream;
};

static inline bsc_t *impl_from_IBindStatusCallback( IBindStatusCallback *iface )
{
    return (bsc_t *)((char*)iface - FIELD_OFFSET(bsc_t, lpVtbl));
}

static HRESULT WINAPI bsc_QueryInterface(
    IBindStatusCallback *iface,
    REFIID riid,
    LPVOID *ppobj )
{
    if (IsEqualGUID(riid, &IID_IUnknown) ||
        IsEqualGUID(riid, &IID_IBindStatusCallback))
    {
        IBindStatusCallback_AddRef( iface );
        *ppobj = iface;
        return S_OK;
    }

    TRACE("interface %s not implemented\n", debugstr_guid(riid));
    return E_NOINTERFACE;
}

static ULONG WINAPI bsc_AddRef(
    IBindStatusCallback *iface )
{
    bsc_t *This = impl_from_IBindStatusCallback(iface);
    LONG ref = InterlockedIncrement(&This->ref);

    TRACE("(%p) ref=%d\n", This, ref);

    return ref;
}

static ULONG WINAPI bsc_Release(
    IBindStatusCallback *iface )
{
    bsc_t *This = impl_from_IBindStatusCallback(iface);
    LONG ref = InterlockedDecrement(&This->ref);

    TRACE("(%p) ref=%d\n", This, ref);

    if(!ref) {
        if (This->binding)   IBinding_Release(This->binding);
        if (This->memstream) IStream_Release(This->memstream);
        heap_free(This);
    }

    return ref;
}

static HRESULT WINAPI bsc_OnStartBinding(
        IBindStatusCallback* iface,
        DWORD dwReserved,
        IBinding* pib)
{
    bsc_t *This = impl_from_IBindStatusCallback(iface);
    HRESULT hr;

    TRACE("(%p)->(%x %p)\n", This, dwReserved, pib);

    This->binding = pib;
    IBinding_AddRef(pib);

    hr = CreateStreamOnHGlobal(NULL, TRUE, &This->memstream);
    if(FAILED(hr))
        return hr;

    return S_OK;
}

static HRESULT WINAPI bsc_GetPriority(
        IBindStatusCallback* iface,
        LONG* pnPriority)
{
    return S_OK;
}

static HRESULT WINAPI bsc_OnLowResource(
        IBindStatusCallback* iface,
        DWORD reserved)
{
    return S_OK;
}

static HRESULT WINAPI bsc_OnProgress(
        IBindStatusCallback* iface,
        ULONG ulProgress,
        ULONG ulProgressMax,
        ULONG ulStatusCode,
        LPCWSTR szStatusText)
{
    return S_OK;
}

static HRESULT WINAPI bsc_OnStopBinding(
        IBindStatusCallback* iface,
        HRESULT hresult,
        LPCWSTR szError)
{
    bsc_t *This = impl_from_IBindStatusCallback(iface);
    HRESULT hr = S_OK;

    TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));

    if(This->binding) {
        IBinding_Release(This->binding);
        This->binding = NULL;
    }

    if(This->obj && SUCCEEDED(hresult)) {
        HGLOBAL hglobal;
        hr = GetHGlobalFromStream(This->memstream, &hglobal);
        if(SUCCEEDED(hr))
        {
            DWORD len = GlobalSize(hglobal);
            char *ptr = GlobalLock(hglobal);

            hr = This->onDataAvailable(This->obj, ptr, len);

            GlobalUnlock(hglobal);
        }
    }

    return hr;
}

static HRESULT WINAPI bsc_GetBindInfo(
        IBindStatusCallback* iface,
        DWORD* grfBINDF,
        BINDINFO* pbindinfo)
{
    *grfBINDF = BINDF_GETNEWESTVERSION|BINDF_PULLDATA|BINDF_RESYNCHRONIZE|BINDF_PRAGMA_NO_CACHE;

    return S_OK;
}

static HRESULT WINAPI bsc_OnDataAvailable(
        IBindStatusCallback* iface,
        DWORD grfBSCF,
        DWORD dwSize,
        FORMATETC* pformatetc,
        STGMEDIUM* pstgmed)
{
    bsc_t *This = impl_from_IBindStatusCallback(iface);
    BYTE buf[4096];
    DWORD read, written;
    HRESULT hr;

    TRACE("(%p)->(%x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);

    do
    {
        hr = IStream_Read(pstgmed->u.pstm, buf, sizeof(buf), &read);
        if(FAILED(hr))
            break;

        hr = IStream_Write(This->memstream, buf, read, &written);
    } while(SUCCEEDED(hr) && written != 0 && read != 0);

    return S_OK;
}

static HRESULT WINAPI bsc_OnObjectAvailable(
        IBindStatusCallback* iface,
        REFIID riid,
        IUnknown* punk)
{
    return S_OK;
}

static const struct IBindStatusCallbackVtbl bsc_vtbl =
{
    bsc_QueryInterface,
    bsc_AddRef,
    bsc_Release,
    bsc_OnStartBinding,
    bsc_GetPriority,
    bsc_OnLowResource,
    bsc_OnProgress,
    bsc_OnStopBinding,
    bsc_GetBindInfo,
    bsc_OnDataAvailable,
    bsc_OnObjectAvailable
};

HRESULT bind_url(LPCWSTR url, HRESULT (*onDataAvailable)(void*,char*,DWORD), void *obj, bsc_t **ret)
{
    WCHAR fileUrl[INTERNET_MAX_URL_LENGTH];
    bsc_t *bsc;
    IBindCtx *pbc;
    HRESULT hr;

    TRACE("%s\n", debugstr_w(url));

    if(!PathIsURLW(url))
    {
        WCHAR fullpath[MAX_PATH];
        DWORD needed = sizeof(fileUrl)/sizeof(WCHAR);

        if(!PathSearchAndQualifyW(url, fullpath, sizeof(fullpath)/sizeof(WCHAR)))
        {
            WARN("can't find path\n");
            return E_FAIL;
        }

        if(FAILED(UrlCreateFromPathW(url, fileUrl, &needed, 0)))
        {
            ERR("can't create url from path\n");
            return E_FAIL;
        }
        url = fileUrl;
    }

    hr = CreateBindCtx(0, &pbc);
    if(FAILED(hr))
        return hr;

    bsc = heap_alloc(sizeof(bsc_t));

    bsc->lpVtbl = &bsc_vtbl;
    bsc->ref = 1;
    bsc->obj = obj;
    bsc->onDataAvailable = onDataAvailable;
    bsc->binding = NULL;
    bsc->memstream = NULL;

    hr = RegisterBindStatusCallback(pbc, (IBindStatusCallback*)&bsc->lpVtbl, NULL, 0);
    if(SUCCEEDED(hr))
    {
        IMoniker *moniker;

        hr = CreateURLMoniker(NULL, url, &moniker);
        if(SUCCEEDED(hr))
        {
            IStream *stream;
            hr = IMoniker_BindToStorage(moniker, pbc, NULL, &IID_IStream, (LPVOID*)&stream);
            IMoniker_Release(moniker);
            if(stream)
                IStream_Release(stream);
        }
        IBindCtx_Release(pbc);
    }

    if(FAILED(hr))
    {
        IBindStatusCallback_Release((IBindStatusCallback*)&bsc->lpVtbl);
        bsc = NULL;
    }

    *ret = bsc;
    return hr;
}

void detach_bsc(bsc_t *bsc)
{
    if(bsc->binding)
        IBinding_Abort(bsc->binding);

    bsc->obj = NULL;
    IBindStatusCallback_Release((IBindStatusCallback*)&bsc->lpVtbl);
}
