/*
 * Copyright 2007 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 "urlmon_main.h"
#include "wine/debug.h"

#define NO_SHLWAPI_REG
#include "shlwapi.h"

WINE_DEFAULT_DEBUG_CHANNEL(urlmon);

typedef struct {
    IInternetProtocolEx IInternetProtocolEx_iface;

    LONG ref;

    IStream *stream;
} MkProtocol;

static inline MkProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface)
{
    return CONTAINING_RECORD(iface, MkProtocol, IInternetProtocolEx_iface);
}

static HRESULT WINAPI MkProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
{
    MkProtocol *This = impl_from_IInternetProtocolEx(iface);

    *ppv = NULL;
    if(IsEqualGUID(&IID_IUnknown, riid)) {
        TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
        *ppv = &This->IInternetProtocolEx_iface;
    }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
        TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
        *ppv = &This->IInternetProtocolEx_iface;
    }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
        TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
        *ppv = &This->IInternetProtocolEx_iface;
    }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
        TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv);
        *ppv = &This->IInternetProtocolEx_iface;
    }

    if(*ppv) {
        IInternetProtocol_AddRef(iface);
        return S_OK;
    }

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

static ULONG WINAPI MkProtocol_AddRef(IInternetProtocolEx *iface)
{
    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
    LONG ref = InterlockedIncrement(&This->ref);
    TRACE("(%p) ref=%d\n", This, ref);
    return ref;
}

static ULONG WINAPI MkProtocol_Release(IInternetProtocolEx *iface)
{
    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
    LONG ref = InterlockedDecrement(&This->ref);

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

    if(!ref) {
        if(This->stream)
            IStream_Release(This->stream);

        heap_free(This);

        URLMON_UnlockModule();
    }

    return ref;
}

static HRESULT report_result(IInternetProtocolSink *sink, HRESULT hres, DWORD dwError)
{
    IInternetProtocolSink_ReportResult(sink, hres, dwError, NULL);
    return hres;
}

static HRESULT WINAPI MkProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
        IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
        DWORD grfPI, HANDLE_PTR dwReserved)
{
    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
    HRESULT hres;
    IUri *uri;

    TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
            pOIBindInfo, grfPI, dwReserved);

    hres = CreateUri(szUrl, 0, 0, &uri);
    if(FAILED(hres))
        return hres;

    hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink,
            pOIBindInfo, grfPI, (HANDLE*)dwReserved);

    IUri_Release(uri);
    return hres;
}

static HRESULT WINAPI MkProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
{
    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
    FIXME("(%p)->(%p)\n", This, pProtocolData);
    return E_NOTIMPL;
}

static HRESULT WINAPI MkProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
        DWORD dwOptions)
{
    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
    FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
    return E_NOTIMPL;
}

static HRESULT WINAPI MkProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
{
    MkProtocol *This = impl_from_IInternetProtocolEx(iface);

    TRACE("(%p)->(%08x)\n", This, dwOptions);

    return S_OK;
}

static HRESULT WINAPI MkProtocol_Suspend(IInternetProtocolEx *iface)
{
    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
    FIXME("(%p)\n", This);
    return E_NOTIMPL;
}

static HRESULT WINAPI MkProtocol_Resume(IInternetProtocolEx *iface)
{
    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
    FIXME("(%p)\n", This);
    return E_NOTIMPL;
}

static HRESULT WINAPI MkProtocol_Read(IInternetProtocolEx *iface, void *pv,
        ULONG cb, ULONG *pcbRead)
{
    MkProtocol *This = impl_from_IInternetProtocolEx(iface);

    TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);

    if(!This->stream)
        return E_FAIL;

    return IStream_Read(This->stream, pv, cb, pcbRead);
}

static HRESULT WINAPI MkProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
        DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
{
    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
    FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
    return E_NOTIMPL;
}

static HRESULT WINAPI MkProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
{
    MkProtocol *This = impl_from_IInternetProtocolEx(iface);

    TRACE("(%p)->(%08x)\n", This, dwOptions);

    return S_OK;
}

static HRESULT WINAPI MkProtocol_UnlockRequest(IInternetProtocolEx *iface)
{
    MkProtocol *This = impl_from_IInternetProtocolEx(iface);

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

    return S_OK;
}

static HRESULT WINAPI MkProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri,
        IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
        DWORD grfPI, HANDLE *dwReserved)
{
    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
    LPWSTR mime, progid, display_name, colon_ptr;
    DWORD path_size = INTERNET_MAX_URL_LENGTH;
    DWORD bindf=0, eaten=0, scheme=0, len;
    BSTR url, path_tmp, path = NULL;
    IParseDisplayName *pdn;
    BINDINFO bindinfo;
    STATSTG statstg;
    IMoniker *mon;
    HRESULT hres;
    CLSID clsid;

    TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink,
            pOIBindInfo, grfPI, dwReserved);

    hres = IUri_GetScheme(pUri, &scheme);
    if(FAILED(hres))
        return hres;
    if(scheme != URL_SCHEME_MK)
        return INET_E_INVALID_URL;

    memset(&bindinfo, 0, sizeof(bindinfo));
    bindinfo.cbSize = sizeof(BINDINFO);
    hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &bindf, &bindinfo);
    if(FAILED(hres)) {
        WARN("GetBindInfo failed: %08x\n", hres);
        return hres;
    }

    ReleaseBindInfo(&bindinfo);

    IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, NULL);

    hres = IUri_GetDisplayUri(pUri, &url);
    if(FAILED(hres))
        return hres;
    hres = FindMimeFromData(NULL, url, NULL, 0, NULL, 0, &mime, 0);
    SysFreeString(url);
    if(SUCCEEDED(hres)) {
        IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
        CoTaskMemFree(mime);
    }

    hres = IUri_GetPath(pUri, &path_tmp);
    if(FAILED(hres))
        return hres;
    path = heap_alloc(path_size);
    hres = UrlUnescapeW((LPWSTR)path_tmp, path, &path_size, 0);
    SysFreeString(path_tmp);
    if (FAILED(hres))
    {
        heap_free(path);
        return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, ERROR_INVALID_PARAMETER);
    }
    progid = path+1; /* skip '@' symbol */
    colon_ptr = strchrW(path, ':');
    if(!colon_ptr)
    {
        heap_free(path);
        return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, ERROR_INVALID_PARAMETER);
    }

    len = strlenW(path);
    display_name = heap_alloc((len+1)*sizeof(WCHAR));
    memcpy(display_name, path, (len+1)*sizeof(WCHAR));

    progid[colon_ptr-progid] = 0; /* overwrite ':' with NULL terminator */
    hres = CLSIDFromProgID(progid, &clsid);
    heap_free(path);
    if(FAILED(hres))
    {
        heap_free(display_name);
        return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, ERROR_INVALID_PARAMETER);
    }

    hres = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
            &IID_IParseDisplayName, (void**)&pdn);
    if(FAILED(hres)) {
        WARN("Could not create object %s\n", debugstr_guid(&clsid));
        heap_free(display_name);
        return report_result(pOIProtSink, hres, ERROR_INVALID_PARAMETER);
    }

    hres = IParseDisplayName_ParseDisplayName(pdn, NULL /* FIXME */, display_name, &eaten, &mon);
    heap_free(display_name);
    IParseDisplayName_Release(pdn);
    if(FAILED(hres)) {
        WARN("ParseDisplayName failed: %08x\n", hres);
        return report_result(pOIProtSink, hres, ERROR_INVALID_PARAMETER);
    }

    if(This->stream) {
        IStream_Release(This->stream);
        This->stream = NULL;
    }

    hres = IMoniker_BindToStorage(mon, NULL /* FIXME */, NULL, &IID_IStream, (void**)&This->stream);
    IMoniker_Release(mon);
    if(FAILED(hres)) {
        WARN("BindToStorage failed: %08x\n", hres);
        return report_result(pOIProtSink, hres, ERROR_INVALID_PARAMETER);
    }

    hres = IStream_Stat(This->stream, &statstg, STATFLAG_NONAME);
    if(FAILED(hres)) {
        WARN("Stat failed: %08x\n", hres);
        return report_result(pOIProtSink, hres, ERROR_INVALID_PARAMETER);
    }

    IInternetProtocolSink_ReportData(pOIProtSink,
            BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION,
            statstg.cbSize.u.LowPart, statstg.cbSize.u.LowPart);
    return report_result(pOIProtSink, S_OK, ERROR_SUCCESS);
}

static const IInternetProtocolExVtbl MkProtocolVtbl = {
    MkProtocol_QueryInterface,
    MkProtocol_AddRef,
    MkProtocol_Release,
    MkProtocol_Start,
    MkProtocol_Continue,
    MkProtocol_Abort,
    MkProtocol_Terminate,
    MkProtocol_Suspend,
    MkProtocol_Resume,
    MkProtocol_Read,
    MkProtocol_Seek,
    MkProtocol_LockRequest,
    MkProtocol_UnlockRequest,
    MkProtocol_StartEx
};

HRESULT MkProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
{
    MkProtocol *ret;

    TRACE("(%p %p)\n", pUnkOuter, ppobj);

    URLMON_LockModule();

    ret = heap_alloc(sizeof(MkProtocol));

    ret->IInternetProtocolEx_iface.lpVtbl = &MkProtocolVtbl;
    ret->ref = 1;
    ret->stream = NULL;

    /* NOTE:
     * Native returns NULL ppobj and S_OK in CreateInstance if called with IID_IUnknown riid.
     */
    *ppobj = &ret->IInternetProtocolEx_iface;

    return S_OK;
}
