/*
 * Copyright 2005 Jacek 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
 */

#include <stdarg.h>

#define COBJMACROS
#define NONAMELESSUNION

#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "oaidl.h"
#include "oleauto.h"
#include "variant.h"

#include "wine/unicode.h"
#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(ole);

typedef struct {
    enum VARENUM vt;
    VARKIND varkind;
    ULONG offset;
    BSTR name;
} fieldstr;

typedef struct {
    IRecordInfo IRecordInfo_iface;
    LONG ref;

    GUID guid;
    UINT lib_index;
    WORD n_vars;
    ULONG size;
    BSTR name;
    fieldstr *fields;
    ITypeInfo *pTypeInfo;
} IRecordInfoImpl;

static inline IRecordInfoImpl *impl_from_IRecordInfo(IRecordInfo *iface)
{
    return CONTAINING_RECORD(iface, IRecordInfoImpl, IRecordInfo_iface);
}

static HRESULT copy_to_variant(void *src, VARIANT *pvar, enum VARENUM vt)
{
    TRACE("%p %p %d\n", src, pvar, vt);

#define CASE_COPY(x) \
    case VT_ ## x: \
        memcpy(&V_ ## x(pvar), src, sizeof(V_ ## x(pvar))); \
        break 

    switch(vt) {
        CASE_COPY(I2);
        CASE_COPY(I4);
        CASE_COPY(R4);
        CASE_COPY(R8);
        CASE_COPY(CY);
        CASE_COPY(DATE);
        CASE_COPY(BSTR);
        CASE_COPY(ERROR);
        CASE_COPY(BOOL);
        CASE_COPY(DECIMAL);
        CASE_COPY(I1);
        CASE_COPY(UI1);
        CASE_COPY(UI2);
        CASE_COPY(UI4);
        CASE_COPY(I8);
        CASE_COPY(UI8);
        CASE_COPY(INT);
        CASE_COPY(UINT);
        CASE_COPY(INT_PTR);
        CASE_COPY(UINT_PTR);
    default:
        FIXME("Not supported type: %d\n", vt);
        return E_NOTIMPL;
    };
#undef CASE_COPY

    V_VT(pvar) = vt;
    return S_OK;
}

static HRESULT copy_from_variant(VARIANT *src, void *dest, enum VARENUM vt)
{
    VARIANT var;
    HRESULT hres;

    TRACE("(%p(%d) %p %d)\n", src, V_VT(src), dest, vt);

    hres = VariantChangeType(&var, src, 0, vt);
    if(FAILED(hres))
        return hres;

#define CASE_COPY(x) \
    case VT_ ## x: \
        memcpy(dest, &V_ ## x(&var), sizeof(V_ ## x(&var))); \
        break

    switch(vt) {
        CASE_COPY(I2);
        CASE_COPY(I4);
        CASE_COPY(R4);
        CASE_COPY(R8);
        CASE_COPY(CY);
        CASE_COPY(DATE);
        CASE_COPY(BSTR);
        CASE_COPY(ERROR);
        CASE_COPY(BOOL);
        CASE_COPY(DECIMAL);
        CASE_COPY(I1);
        CASE_COPY(UI1);
        CASE_COPY(UI2);
        CASE_COPY(UI4);
        CASE_COPY(I8);
        CASE_COPY(UI8);
        CASE_COPY(INT);
        CASE_COPY(UINT);
        CASE_COPY(INT_PTR);
        CASE_COPY(UINT_PTR);
    default:
        FIXME("Not supported type: %d\n", V_VT(&var));
        return E_NOTIMPL;
    };
#undef CASE_COPY
    return S_OK;
}

static HRESULT WINAPI IRecordInfoImpl_QueryInterface(IRecordInfo *iface, REFIID riid,
                                                void **ppvObject)
{
    TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);

    *ppvObject = NULL;

    if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IRecordInfo, riid)) {
       *ppvObject = iface;
       IRecordInfo_AddRef(iface);
       return S_OK;
    }

    FIXME("Not supported interface: %s\n", debugstr_guid(riid));
    return E_NOINTERFACE;
}

static ULONG WINAPI IRecordInfoImpl_AddRef(IRecordInfo *iface)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
    ULONG ref = InterlockedIncrement(&This->ref);
    TRACE("(%p) -> %d\n", This, ref);
    return ref;
}

static ULONG WINAPI IRecordInfoImpl_Release(IRecordInfo *iface)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
    ULONG ref = InterlockedDecrement(&This->ref);

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

    if(!ref) {
        int i;
        for(i=0; i<This->n_vars; i++)
            SysFreeString(This->fields[i].name);
        SysFreeString(This->name);
        HeapFree(GetProcessHeap(), 0, This->fields);
        ITypeInfo_Release(This->pTypeInfo);
        HeapFree(GetProcessHeap(), 0, This);
    }
    return ref;
}

static HRESULT WINAPI IRecordInfoImpl_RecordInit(IRecordInfo *iface, PVOID pvNew)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
    TRACE("(%p)->(%p)\n", This, pvNew);

    if(!pvNew)
        return E_INVALIDARG;

    memset(pvNew, 0, This->size);
    return S_OK;
}

static HRESULT WINAPI IRecordInfoImpl_RecordClear(IRecordInfo *iface, PVOID pvExisting)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
    int i;
    PVOID var;

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

    if(!pvExisting)
        return E_INVALIDARG;

    for(i=0; i<This->n_vars; i++) {
        if(This->fields[i].varkind != VAR_PERINSTANCE) {
            ERR("varkind != VAR_PERINSTANCE\n");
            continue;
        }
        var = ((PBYTE)pvExisting)+This->fields[i].offset;
        switch(This->fields[i].vt) {
            case VT_BSTR:
               SysFreeString(*(BSTR*)var);
                *(BSTR*)var = NULL;
                break;
            case VT_I2:
            case VT_I4:
            case VT_R4:
            case VT_R8:
            case VT_CY:
            case VT_DATE:
            case VT_ERROR:
            case VT_BOOL:
            case VT_DECIMAL:
            case VT_I1:
            case VT_UI1:
            case VT_UI2:
            case VT_UI4:
            case VT_I8:
            case VT_UI8:
            case VT_INT:
            case VT_UINT:
            case VT_HRESULT:
                break;
            case VT_INT_PTR:
            case VT_UINT_PTR:
                *(void**)var = NULL;
                break;
            case VT_SAFEARRAY:
                SafeArrayDestroy(var);
                break;
            case VT_UNKNOWN:
            case VT_DISPATCH:
            {
                IUnknown *unk = *(IUnknown**)var;
                if (unk)
                    IUnknown_Release(unk);
                *(void**)var = NULL;
                break;
            }
            default:
                FIXME("Not supported vt = %d\n", This->fields[i].vt);
                break;
        }
    }
    
    return S_OK;
}

static HRESULT WINAPI IRecordInfoImpl_RecordCopy(IRecordInfo *iface, void *src_rec, void *dest_rec)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
    HRESULT hr = S_OK;
    int i;

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

    if(!src_rec || !dest_rec)
        return E_INVALIDARG;

    /* release already stored data */
    IRecordInfo_RecordClear(iface, dest_rec);

    for (i = 0; i < This->n_vars; i++)
    {
        void *src, *dest;

        if (This->fields[i].varkind != VAR_PERINSTANCE) {
            ERR("varkind != VAR_PERINSTANCE\n");
            continue;
        }

        src  = ((BYTE*)src_rec) + This->fields[i].offset;
        dest = ((BYTE*)dest_rec) + This->fields[i].offset;
        switch (This->fields[i].vt)
        {
            case VT_BSTR:
            {
                BSTR src_str = *(BSTR*)src;

                if (src_str)
                {
                    BSTR str = SysAllocString(*(BSTR*)src);
                    if (!str) hr = E_OUTOFMEMORY;

                    *(BSTR*)dest = str;
                }
                else
                    *(BSTR*)dest = NULL;
                break;
            }
            case VT_UNKNOWN:
            case VT_DISPATCH:
            {
                IUnknown *unk = *(IUnknown**)src;
                *(IUnknown**)dest = unk;
                if (unk) IUnknown_AddRef(unk);
                break;
            }
            case VT_SAFEARRAY:
                hr = SafeArrayCopy(src, dest);
                break;
            default:
            {
                /* copy directly for types that don't need deep copy */
                int len = get_type_size(NULL, This->fields[i].vt);
                memcpy(dest, src, len);
                break;
            }
        }

        if (FAILED(hr)) break;
    }

    if (FAILED(hr))
        IRecordInfo_RecordClear(iface, dest_rec);

    return hr;
}

static HRESULT WINAPI IRecordInfoImpl_GetGuid(IRecordInfo *iface, GUID *pguid)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);

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

    if(!pguid)
        return E_INVALIDARG;

    *pguid = This->guid;
    return S_OK;
}

static HRESULT WINAPI IRecordInfoImpl_GetName(IRecordInfo *iface, BSTR *pbstrName)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);

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

    if(!pbstrName)
        return E_INVALIDARG;

    *pbstrName = SysAllocString(This->name);
    return S_OK;
}

static HRESULT WINAPI IRecordInfoImpl_GetSize(IRecordInfo *iface, ULONG *pcbSize)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);

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

    if(!pcbSize)
        return E_INVALIDARG;
    
    *pcbSize = This->size;
    return S_OK;
}

static HRESULT WINAPI IRecordInfoImpl_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);

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

    if(!ppTypeInfo)
        return E_INVALIDARG;

    ITypeInfo_AddRef(This->pTypeInfo);
    *ppTypeInfo = This->pTypeInfo;

    return S_OK;
}

static HRESULT WINAPI IRecordInfoImpl_GetField(IRecordInfo *iface, PVOID pvData,
                                                LPCOLESTR szFieldName, VARIANT *pvarField)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
    int i;

    TRACE("(%p)->(%p %s %p)\n", This, pvData, debugstr_w(szFieldName), pvarField);

    if(!pvData || !szFieldName || !pvarField)
        return E_INVALIDARG;

    for(i=0; i<This->n_vars; i++)
        if(!strcmpW(This->fields[i].name, szFieldName))
            break;
    if(i == This->n_vars)
        return TYPE_E_FIELDNOTFOUND;
    
    VariantClear(pvarField);
    return copy_to_variant(((PBYTE)pvData)+This->fields[i].offset, pvarField,
            This->fields[i].vt);
}

static HRESULT WINAPI IRecordInfoImpl_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData,
                            LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
    int i;

    TRACE("(%p)->(%p %s %p %p)\n", This, pvData, debugstr_w(szFieldName), pvarField, ppvDataCArray);

    if(!pvData || !szFieldName || !pvarField)
        return E_INVALIDARG;

    for(i=0; i<This->n_vars; i++)
        if(!strcmpW(This->fields[i].name, szFieldName))
            break;
    if(i == This->n_vars)
        return TYPE_E_FIELDNOTFOUND;

    VariantClear(pvarField);
    V_VT(pvarField) = VT_BYREF|This->fields[i].vt;
    V_BYREF(pvarField) = ((PBYTE)pvData)+This->fields[i].offset;
    *ppvDataCArray = NULL;
    return S_OK;
}

static HRESULT WINAPI IRecordInfoImpl_PutField(IRecordInfo *iface, ULONG wFlags, PVOID pvData,
                                            LPCOLESTR szFieldName, VARIANT *pvarField)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
    int i;

    TRACE("(%p)->(%08x %p %s %p)\n", This, wFlags, pvData, debugstr_w(szFieldName),
                                    pvarField);

    if(!pvData || !szFieldName || !pvarField
            || (wFlags != INVOKE_PROPERTYPUTREF && wFlags != INVOKE_PROPERTYPUT))
        return E_INVALIDARG;

    if(wFlags == INVOKE_PROPERTYPUTREF) {
        FIXME("wFlag == INVOKE_PROPERTYPUTREF not supported\n");
        return E_NOTIMPL;
    }

    for(i=0; i<This->n_vars; i++)
        if(!strcmpW(This->fields[i].name, szFieldName))
            break;
    if(i == This->n_vars)
        return TYPE_E_FIELDNOTFOUND;

    return copy_from_variant(pvarField, ((PBYTE)pvData)+This->fields[i].offset,
            This->fields[i].vt);
}

static HRESULT WINAPI IRecordInfoImpl_PutFieldNoCopy(IRecordInfo *iface, ULONG wFlags,
                PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
    int i;

    FIXME("(%p)->(%08x %p %s %p) stub\n", This, wFlags, pvData, debugstr_w(szFieldName), pvarField);

    if(!pvData || !szFieldName || !pvarField
            || (wFlags != INVOKE_PROPERTYPUTREF && wFlags != INVOKE_PROPERTYPUT))
        return E_INVALIDARG;

    for(i=0; i<This->n_vars; i++)
        if(!strcmpW(This->fields[i].name, szFieldName))
            break;
    if(i == This->n_vars)
        return TYPE_E_FIELDNOTFOUND;

    return E_NOTIMPL;
}

static HRESULT WINAPI IRecordInfoImpl_GetFieldNames(IRecordInfo *iface, ULONG *pcNames,
                                                BSTR *rgBstrNames)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
    ULONG n = This->n_vars, i;

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

    if(!pcNames)
        return E_INVALIDARG;

    if(*pcNames < n)
        n =  *pcNames;

    if(rgBstrNames) {
        for(i=0; i<n; i++)
            rgBstrNames[i] = SysAllocString(This->fields[i].name);
    }
    
    *pcNames = n;
    return S_OK;
}

static BOOL WINAPI IRecordInfoImpl_IsMatchingType(IRecordInfo *iface, IRecordInfo *info2)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
    GUID guid2;

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

    IRecordInfo_GetGuid( info2, &guid2 );
    return IsEqualGUID( &This->guid, &guid2 );
}

static PVOID WINAPI IRecordInfoImpl_RecordCreate(IRecordInfo *iface)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
    void *record;

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

    record = HeapAlloc(GetProcessHeap(), 0, This->size);
    IRecordInfo_RecordInit(iface, record);
    TRACE("created record at %p\n", record);
    return record;
}

static HRESULT WINAPI IRecordInfoImpl_RecordCreateCopy(IRecordInfo *iface, PVOID pvSource,
                                                    PVOID *ppvDest)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);

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

    if(!pvSource || !ppvDest)
        return E_INVALIDARG;
    
    *ppvDest = IRecordInfo_RecordCreate(iface);
    return IRecordInfo_RecordCopy(iface, pvSource, *ppvDest);
}

static HRESULT WINAPI IRecordInfoImpl_RecordDestroy(IRecordInfo *iface, PVOID pvRecord)
{
    IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
    HRESULT hres;

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

    hres = IRecordInfo_RecordClear(iface, pvRecord);
    if(FAILED(hres))
        return hres;

    if(!HeapFree(GetProcessHeap(), 0, pvRecord))
        return E_INVALIDARG;

    return S_OK;
}

static const IRecordInfoVtbl IRecordInfoImplVtbl = {
    IRecordInfoImpl_QueryInterface,
    IRecordInfoImpl_AddRef,
    IRecordInfoImpl_Release,
    IRecordInfoImpl_RecordInit,
    IRecordInfoImpl_RecordClear,
    IRecordInfoImpl_RecordCopy,
    IRecordInfoImpl_GetGuid,
    IRecordInfoImpl_GetName,
    IRecordInfoImpl_GetSize,
    IRecordInfoImpl_GetTypeInfo,
    IRecordInfoImpl_GetField,
    IRecordInfoImpl_GetFieldNoCopy,
    IRecordInfoImpl_PutField,
    IRecordInfoImpl_PutFieldNoCopy,
    IRecordInfoImpl_GetFieldNames,
    IRecordInfoImpl_IsMatchingType,
    IRecordInfoImpl_RecordCreate,
    IRecordInfoImpl_RecordCreateCopy,
    IRecordInfoImpl_RecordDestroy
};

/******************************************************************************
 *      GetRecordInfoFromGuids  [OLEAUT32.322]
 *
 * RETURNS
 *  Success: S_OK
 *  Failure: E_INVALIDARG, if any argument is invalid.
 */
HRESULT WINAPI GetRecordInfoFromGuids(REFGUID rGuidTypeLib, ULONG uVerMajor,
                        ULONG uVerMinor, LCID lcid, REFGUID rGuidTypeInfo, IRecordInfo** ppRecInfo)
{
    ITypeInfo *pTypeInfo;
    ITypeLib *pTypeLib;
    HRESULT hres;
    
    TRACE("(%p,%d,%d,%d,%s,%p)\n", rGuidTypeLib, uVerMajor, uVerMinor,
            lcid, debugstr_guid(rGuidTypeInfo), ppRecInfo);

    hres = LoadRegTypeLib(rGuidTypeLib, uVerMajor, uVerMinor, lcid, &pTypeLib);
    if(FAILED(hres)) {
        WARN("LoadRegTypeLib failed!\n");
        return hres;
    }

    hres = ITypeLib_GetTypeInfoOfGuid(pTypeLib, rGuidTypeInfo, &pTypeInfo);
    ITypeLib_Release(pTypeLib);
    if(FAILED(hres)) {
        WARN("GetTypeInfoOfGuid failed!\n");
        return hres;
    }

    hres = GetRecordInfoFromTypeInfo(pTypeInfo, ppRecInfo);
    ITypeInfo_Release(pTypeInfo);
    return hres;
}

/******************************************************************************
 *      GetRecordInfoFromTypeInfo [OLEAUT32.332]
 */
HRESULT WINAPI GetRecordInfoFromTypeInfo(ITypeInfo* pTI, IRecordInfo** ppRecInfo) {
    HRESULT hres;
    TYPEATTR *typeattr;
    IRecordInfoImpl *ret;
    ITypeInfo *pTypeInfo;
    int i;
    GUID guid;

    TRACE("(%p %p)\n", pTI, ppRecInfo);

    if(!pTI || !ppRecInfo)
        return E_INVALIDARG;
    
    hres = ITypeInfo_GetTypeAttr(pTI, &typeattr);
    if(FAILED(hres) || !typeattr) {
        WARN("GetTypeAttr failed: %08x\n", hres);
        return hres;
    }

    if(typeattr->typekind == TKIND_ALIAS) {
        hres = ITypeInfo_GetRefTypeInfo(pTI, typeattr->tdescAlias.u.hreftype, &pTypeInfo);
        guid = typeattr->guid;
        ITypeInfo_ReleaseTypeAttr(pTI, typeattr);
        if(FAILED(hres)) {
            WARN("GetRefTypeInfo failed: %08x\n", hres);
            return hres;
        }
        hres = ITypeInfo_GetTypeAttr(pTypeInfo, &typeattr);
        if(FAILED(hres)) {
            ITypeInfo_Release(pTypeInfo);
            WARN("GetTypeAttr failed for referenced type: %08x\n", hres);
            return hres;
        }
    }else  {
        pTypeInfo = pTI;
        ITypeInfo_AddRef(pTypeInfo);
        guid = typeattr->guid;
    }

    if(typeattr->typekind != TKIND_RECORD) {
        WARN("typekind != TKIND_RECORD\n");
        ITypeInfo_ReleaseTypeAttr(pTypeInfo, typeattr);
        ITypeInfo_Release(pTypeInfo);
        return E_INVALIDARG;
    }

    ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret));
    ret->IRecordInfo_iface.lpVtbl = &IRecordInfoImplVtbl;
    ret->ref = 1;
    ret->pTypeInfo = pTypeInfo;
    ret->n_vars = typeattr->cVars;
    ret->size = typeattr->cbSizeInstance;
    ITypeInfo_ReleaseTypeAttr(pTypeInfo, typeattr);

    ret->guid = guid;

    /* NOTE: Windows implementation calls ITypeInfo::GetCantainingTypeLib and
     *       ITypeLib::GetLibAttr, but we currently don't need this.
     */

    hres = ITypeInfo_GetDocumentation(pTypeInfo, MEMBERID_NIL, &ret->name, NULL, NULL, NULL);
    if(FAILED(hres)) {
        WARN("ITypeInfo::GetDocumentation failed\n");
        ret->name = NULL;
    }

    ret->fields = HeapAlloc(GetProcessHeap(), 0, ret->n_vars*sizeof(fieldstr));
    for(i = 0; i<ret->n_vars; i++) {
        VARDESC *vardesc;
        hres = ITypeInfo_GetVarDesc(pTypeInfo, i, &vardesc);
        if(FAILED(hres)) {
            WARN("GetVarDesc failed\n");
            continue;
        }
        ret->fields[i].vt = vardesc->elemdescVar.tdesc.vt;
        ret->fields[i].varkind = vardesc->varkind;
        ret->fields[i].offset = vardesc->u.oInst;
        hres = ITypeInfo_GetDocumentation(pTypeInfo, vardesc->memid, &ret->fields[i].name,
                NULL, NULL, NULL);
        if(FAILED(hres))
            WARN("GetDocumentation failed: %08x\n", hres);
        TRACE("field=%s, offset=%d\n", debugstr_w(ret->fields[i].name), ret->fields[i].offset);
        ITypeInfo_ReleaseVarDesc(pTypeInfo, vardesc);
    }

    *ppRecInfo = &ret->IRecordInfo_iface;

    return S_OK;
}
