/*
 * Copyright 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 "config.h"

#include <stdarg.h>
#include <stdio.h>

#define COBJMACROS

#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "ole2.h"
#include "optary.h"

#include "wine/debug.h"

#include "mshtml_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(mshtml);

typedef struct load_opt {
    DWORD option;
    PVOID buffer;
    DWORD size;

    struct load_opt *next;
} load_opt;

typedef struct {
    IHtmlLoadOptions IHtmlLoadOptions_iface;

    LONG ref;

    load_opt *opts;
} HTMLLoadOptions;

static inline HTMLLoadOptions *impl_from_IHtmlLoadOptions(IHtmlLoadOptions *iface)
{
    return CONTAINING_RECORD(iface, HTMLLoadOptions, IHtmlLoadOptions_iface);
}

static HRESULT WINAPI HtmlLoadOptions_QueryInterface(IHtmlLoadOptions *iface,
        REFIID riid, void **ppv)
{
    HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface);

    TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);

    if(IsEqualGUID(&IID_IUnknown, riid)) {
        *ppv = &This->IHtmlLoadOptions_iface;
    }else if(IsEqualGUID(&IID_IOptionArray, riid)) {
        *ppv = &This->IHtmlLoadOptions_iface;
    }else if(IsEqualGUID(&IID_IHtmlLoadOptions, riid)) {
        *ppv = &This->IHtmlLoadOptions_iface;
    }else {
        *ppv = NULL;
        WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
        return E_NOINTERFACE;
    }

    IUnknown_AddRef((IUnknown*)*ppv);
    return S_OK;
}

static ULONG WINAPI HtmlLoadOptions_AddRef(IHtmlLoadOptions *iface)
{
    HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface);
    LONG ref = InterlockedIncrement(&This->ref);

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

    return ref;
}

static ULONG WINAPI HtmlLoadOptions_Release(IHtmlLoadOptions *iface)
{
    HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface);
    LONG ref = InterlockedDecrement(&This->ref);

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

    if(!ref) {
        load_opt *iter = This->opts, *last;

        while(iter) {
            last = iter;
            iter = iter->next;

            heap_free(last->buffer);
            heap_free(last);
        }

        heap_free(This);
    }

    return ref;
}

static HRESULT WINAPI HtmlLoadOptions_QueryOption(IHtmlLoadOptions *iface, DWORD dwOption,
        LPVOID pBuffer, ULONG *pcbBuf)
{
    HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface);
    load_opt *iter;

    TRACE("(%p)->(%d %p %p)\n", This, dwOption, pBuffer, pcbBuf);

    for(iter = This->opts; iter; iter = iter->next) {
        if(iter->option == dwOption)
            break;
    }

    if(!iter) {
        *pcbBuf = 0;
        return S_OK;
    }

    if(*pcbBuf < iter->size) {
        *pcbBuf = iter->size;
        return E_FAIL;
    }

    memcpy(pBuffer, iter->buffer, iter->size);
    *pcbBuf = iter->size;

    return S_OK;
}

static HRESULT WINAPI HtmlLoadOptions_SetOption(IHtmlLoadOptions *iface, DWORD dwOption,
        LPVOID pBuffer, ULONG cbBuf)
{
    HTMLLoadOptions *This = impl_from_IHtmlLoadOptions(iface);
    load_opt *iter = NULL;

    TRACE("(%p)->(%d %p %d)\n", This, dwOption, pBuffer, cbBuf);

    for(iter = This->opts; iter; iter = iter->next) {
        if(iter->option == dwOption)
            break;
    }

    if(!iter) {
        iter = heap_alloc(sizeof(load_opt));
        iter->next = This->opts;
        This->opts = iter;

        iter->option = dwOption;
    }else {
        heap_free(iter->buffer);
    }

    if(!cbBuf) {
        iter->buffer = NULL;
        iter->size = 0;

        return S_OK;
    }

    iter->size = cbBuf;
    iter->buffer = heap_alloc(cbBuf);
    memcpy(iter->buffer, pBuffer, iter->size);

    return S_OK;
}

static const IHtmlLoadOptionsVtbl HtmlLoadOptionsVtbl = {
    HtmlLoadOptions_QueryInterface,
    HtmlLoadOptions_AddRef,
    HtmlLoadOptions_Release,
    HtmlLoadOptions_QueryOption,
    HtmlLoadOptions_SetOption
};

HRESULT HTMLLoadOptions_Create(IUnknown *pUnkOuter, REFIID riid, void** ppv)
{
    HTMLLoadOptions *ret;
    HRESULT hres;

    TRACE("(%p %s %p)\n", pUnkOuter, debugstr_mshtml_guid(riid), ppv);

    ret = heap_alloc(sizeof(HTMLLoadOptions));
    if(!ret)
        return E_OUTOFMEMORY;

    ret->IHtmlLoadOptions_iface.lpVtbl = &HtmlLoadOptionsVtbl;
    ret->ref = 1;
    ret->opts = NULL;

    hres = IHtmlLoadOptions_QueryInterface(&ret->IHtmlLoadOptions_iface, riid, ppv);
    IHtmlLoadOptions_Release(&ret->IHtmlLoadOptions_iface);
    return hres;
}
