/*
 *    DOM Document Implementation implementation
 *
 * Copyright 2007 Alistair Leslie-Hughes
 *
 * 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

#include "config.h"

#include <stdarg.h>
#ifdef HAVE_LIBXML2
# include <libxml/parser.h>
# include <libxml/xmlerror.h>
#endif

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

#include "msxml_private.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(msxml);

#ifdef HAVE_LIBXML2

typedef struct _domimpl
{
    IXMLDOMImplementation IXMLDOMImplementation_iface;
    LONG ref;
} domimpl;

static inline domimpl *impl_from_IXMLDOMImplementation( IXMLDOMImplementation *iface )
{
    return CONTAINING_RECORD(iface, domimpl, IXMLDOMImplementation_iface);
}

static HRESULT WINAPI dimimpl_QueryInterface(
    IXMLDOMImplementation *iface,
    REFIID riid,
    void** ppvObject )
{
    domimpl *This = impl_from_IXMLDOMImplementation( iface );
    TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);

    if ( IsEqualGUID( riid, &IID_IXMLDOMImplementation ) ||
         IsEqualGUID( riid, &IID_IDispatch ) ||
         IsEqualGUID( riid, &IID_IUnknown ) )
    {
        *ppvObject = iface;
    }
    else
    {
        TRACE("Unsupported interface %s\n", debugstr_guid(riid));
        *ppvObject = NULL;
        return E_NOINTERFACE;
    }

    IXMLDOMImplementation_AddRef( iface );

    return S_OK;
}

static ULONG WINAPI dimimpl_AddRef(
    IXMLDOMImplementation *iface )
{
    domimpl *This = impl_from_IXMLDOMImplementation( iface );
    ULONG ref = InterlockedIncrement( &This->ref );
    TRACE("(%p)->(%d)\n", This, ref);
    return ref;
}

static ULONG WINAPI dimimpl_Release(
    IXMLDOMImplementation *iface )
{
    domimpl *This = impl_from_IXMLDOMImplementation( iface );
    ULONG ref = InterlockedDecrement( &This->ref );

    TRACE("(%p)->(%d)\n", This, ref);
    if ( ref == 0 )
    {
        heap_free( This );
    }

    return ref;
}

static HRESULT WINAPI dimimpl_GetTypeInfoCount(
    IXMLDOMImplementation *iface,
    UINT* pctinfo )
{
    domimpl *This = impl_from_IXMLDOMImplementation( iface );

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

    *pctinfo = 1;

    return S_OK;
}

static HRESULT WINAPI dimimpl_GetTypeInfo(
    IXMLDOMImplementation *iface,
    UINT iTInfo, LCID lcid,
    ITypeInfo** ppTInfo )
{
    domimpl *This = impl_from_IXMLDOMImplementation( iface );
    HRESULT hr;

    TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);

    hr = get_typeinfo(IXMLDOMImplementation_tid, ppTInfo);

    return hr;
}

static HRESULT WINAPI dimimpl_GetIDsOfNames(
    IXMLDOMImplementation *iface,
    REFIID riid, LPOLESTR* rgszNames,
    UINT cNames, LCID lcid, DISPID* rgDispId )
{
    domimpl *This = impl_from_IXMLDOMImplementation( iface );
    ITypeInfo *typeinfo;
    HRESULT hr;

    TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
          lcid, rgDispId);

    if(!rgszNames || cNames == 0 || !rgDispId)
        return E_INVALIDARG;

    hr = get_typeinfo(IXMLDOMImplementation_tid, &typeinfo);
    if(SUCCEEDED(hr))
    {
        hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
        ITypeInfo_Release(typeinfo);
    }

    return hr;
}

static HRESULT WINAPI dimimpl_Invoke(
    IXMLDOMImplementation *iface,
    DISPID dispIdMember, REFIID riid, LCID lcid,
    WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
    EXCEPINFO* pExcepInfo, UINT* puArgErr )
{
    domimpl *This = impl_from_IXMLDOMImplementation( iface );
    ITypeInfo *typeinfo;
    HRESULT hr;

    TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
          lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);

    hr = get_typeinfo(IXMLDOMImplementation_tid, &typeinfo);
    if(SUCCEEDED(hr))
    {
        hr = ITypeInfo_Invoke(typeinfo, &This->IXMLDOMImplementation_iface, dispIdMember, wFlags,
                pDispParams, pVarResult, pExcepInfo, puArgErr);
        ITypeInfo_Release(typeinfo);
    }

    return hr;
}

static HRESULT WINAPI dimimpl_hasFeature(IXMLDOMImplementation* This, BSTR feature, BSTR version, VARIANT_BOOL *hasFeature)
{
    static const WCHAR bVersion[] = {'1','.','0',0};
    static const WCHAR bXML[] = {'X','M','L',0};
    static const WCHAR bDOM[] = {'D','O','M',0};
    static const WCHAR bMSDOM[] = {'M','S','-','D','O','M',0};
    BOOL bValidFeature = FALSE;
    BOOL bValidVersion = FALSE;

    TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(feature), debugstr_w(version), hasFeature);

    if(!feature || !hasFeature)
        return E_INVALIDARG;

    *hasFeature = VARIANT_FALSE;

    if(!version || lstrcmpiW(version, bVersion) == 0)
        bValidVersion = TRUE;

    if(lstrcmpiW(feature, bXML) == 0 || lstrcmpiW(feature, bDOM) == 0 || lstrcmpiW(feature, bMSDOM) == 0)
        bValidFeature = TRUE;

    if(bValidVersion && bValidFeature)
        *hasFeature = VARIANT_TRUE;

    return S_OK;
}

static const struct IXMLDOMImplementationVtbl dimimpl_vtbl =
{
    dimimpl_QueryInterface,
    dimimpl_AddRef,
    dimimpl_Release,
    dimimpl_GetTypeInfoCount,
    dimimpl_GetTypeInfo,
    dimimpl_GetIDsOfNames,
    dimimpl_Invoke,
    dimimpl_hasFeature
};

IUnknown* create_doc_Implementation(void)
{
    domimpl *This;

    This = heap_alloc( sizeof *This );
    if ( !This )
        return NULL;

    This->IXMLDOMImplementation_iface.lpVtbl = &dimimpl_vtbl;
    This->ref = 1;

    return (IUnknown*)&This->IXMLDOMImplementation_iface;
}

#endif
