/*
 * Copyright 2012 Hans Leidekker 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>

#define COBJMACROS

#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "wincodec.h"

#include "wincodecs_private.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);

typedef struct ColorContext {
    IWICColorContext IWICColorContext_iface;
    LONG ref;
    WICColorContextType type;
    BYTE *profile;
    UINT profile_len;
    UINT exif_color_space;
} ColorContext;

static inline ColorContext *impl_from_IWICColorContext(IWICColorContext *iface)
{
    return CONTAINING_RECORD(iface, ColorContext, IWICColorContext_iface);
}

static HRESULT WINAPI ColorContext_QueryInterface(IWICColorContext *iface, REFIID iid,
    void **ppv)
{
    ColorContext *This = impl_from_IWICColorContext(iface);
    TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);

    if (!ppv) return E_INVALIDARG;

    if (IsEqualIID(&IID_IUnknown, iid) ||
        IsEqualIID(&IID_IWICColorContext, iid))
    {
        *ppv = &This->IWICColorContext_iface;
    }
    else
    {
        *ppv = NULL;
        return E_NOINTERFACE;
    }

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

static ULONG WINAPI ColorContext_AddRef(IWICColorContext *iface)
{
    ColorContext *This = impl_from_IWICColorContext(iface);
    ULONG ref = InterlockedIncrement(&This->ref);

    TRACE("(%p) refcount=%u\n", iface, ref);

    return ref;
}

static ULONG WINAPI ColorContext_Release(IWICColorContext *iface)
{
    ColorContext *This = impl_from_IWICColorContext(iface);
    ULONG ref = InterlockedDecrement(&This->ref);

    TRACE("(%p) refcount=%u\n", iface, ref);

    if (ref == 0)
    {
        HeapFree(GetProcessHeap(), 0, This->profile);
        HeapFree(GetProcessHeap(), 0, This);
    }

    return ref;
}

static HRESULT load_profile(const WCHAR *filename, BYTE **profile, UINT *len)
{
    HANDLE handle;
    DWORD count;
    LARGE_INTEGER size;
    BOOL ret;

    *len = 0;
    *profile = NULL;
    handle = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
    if (handle == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32(GetLastError());

    if (!(GetFileSizeEx(handle, &size)))
    {
        CloseHandle(handle);
        return HRESULT_FROM_WIN32(GetLastError());
    }
    if (size.u.HighPart)
    {
        WARN("file too large\n");
        CloseHandle(handle);
        return E_FAIL;
    }
    if (!(*profile = HeapAlloc(GetProcessHeap(), 0, size.u.LowPart)))
    {
        CloseHandle(handle);
        return E_OUTOFMEMORY;
    }
    ret = ReadFile(handle, *profile, size.u.LowPart, &count, NULL);
    CloseHandle(handle);
    if (!ret) {
        HeapFree (GetProcessHeap(),0,*profile);
        *profile = NULL;
        return HRESULT_FROM_WIN32(GetLastError());
    }
    if (count != size.u.LowPart) {
        HeapFree (GetProcessHeap(),0,*profile);
        *profile = NULL;
        return E_FAIL;
    }
    *len = count;
    return S_OK;
}

static HRESULT WINAPI ColorContext_InitializeFromFilename(IWICColorContext *iface,
    LPCWSTR wzFilename)
{
    ColorContext *This = impl_from_IWICColorContext(iface);
    BYTE *profile;
    UINT len;
    HRESULT hr;
    TRACE("(%p,%s)\n", iface, debugstr_w(wzFilename));

    if (This->type != WICColorContextUninitialized && This->type != WICColorContextProfile)
        return WINCODEC_ERR_WRONGSTATE;

    if (!wzFilename) return E_INVALIDARG;

    hr = load_profile(wzFilename, &profile, &len);
    if (FAILED(hr)) return hr;

    HeapFree(GetProcessHeap(), 0, This->profile);
    This->profile = profile;
    This->profile_len = len;
    This->type = WICColorContextProfile;

    return S_OK;
}

static HRESULT WINAPI ColorContext_InitializeFromMemory(IWICColorContext *iface,
    const BYTE *pbBuffer, UINT cbBufferSize)
{
    ColorContext *This = impl_from_IWICColorContext(iface);
    BYTE *profile;
    TRACE("(%p,%p,%u)\n", iface, pbBuffer, cbBufferSize);

    if (This->type != WICColorContextUninitialized && This->type != WICColorContextProfile)
        return WINCODEC_ERR_WRONGSTATE;

    if (!(profile = HeapAlloc(GetProcessHeap(), 0, cbBufferSize))) return E_OUTOFMEMORY;
    memcpy(profile, pbBuffer, cbBufferSize);

    HeapFree(GetProcessHeap(), 0, This->profile);
    This->profile = profile;
    This->profile_len = cbBufferSize;
    This->type = WICColorContextProfile;

    return S_OK;
}

static HRESULT WINAPI ColorContext_InitializeFromExifColorSpace(IWICColorContext *iface,
    UINT value)
{
    ColorContext *This = impl_from_IWICColorContext(iface);
    TRACE("(%p,%u)\n", iface, value);

    if (This->type != WICColorContextUninitialized && This->type != WICColorContextExifColorSpace)
        return WINCODEC_ERR_WRONGSTATE;

    This->exif_color_space = value;
    This->type = WICColorContextExifColorSpace;

    return S_OK;
}

static HRESULT WINAPI ColorContext_GetType(IWICColorContext *iface,
    WICColorContextType *pType)
{
    ColorContext *This = impl_from_IWICColorContext(iface);
    TRACE("(%p,%p)\n", iface, pType);

    if (!pType) return E_INVALIDARG;

    *pType = This->type;
    return S_OK;
}

static HRESULT WINAPI ColorContext_GetProfileBytes(IWICColorContext *iface,
    UINT cbBuffer, BYTE *pbBuffer, UINT *pcbActual)
{
    ColorContext *This = impl_from_IWICColorContext(iface);
    TRACE("(%p,%u,%p,%p)\n", iface, cbBuffer, pbBuffer, pcbActual);

    if (This->type != WICColorContextProfile)
        return WINCODEC_ERR_NOTINITIALIZED;

    if (!pcbActual) return E_INVALIDARG;

    if (cbBuffer >= This->profile_len && pbBuffer)
        memcpy(pbBuffer, This->profile, This->profile_len);

    *pcbActual = This->profile_len;

    return S_OK;
}

static HRESULT WINAPI ColorContext_GetExifColorSpace(IWICColorContext *iface,
    UINT *pValue)
{
    ColorContext *This = impl_from_IWICColorContext(iface);
    TRACE("(%p,%p)\n", iface, pValue);

    if (!pValue) return E_INVALIDARG;

    *pValue = This->exif_color_space;
    return S_OK;
}

static const IWICColorContextVtbl ColorContext_Vtbl = {
    ColorContext_QueryInterface,
    ColorContext_AddRef,
    ColorContext_Release,
    ColorContext_InitializeFromFilename,
    ColorContext_InitializeFromMemory,
    ColorContext_InitializeFromExifColorSpace,
    ColorContext_GetType,
    ColorContext_GetProfileBytes,
    ColorContext_GetExifColorSpace
};

HRESULT ColorContext_Create(IWICColorContext **colorcontext)
{
    ColorContext *This;

    if (!colorcontext) return E_INVALIDARG;

    This = HeapAlloc(GetProcessHeap(), 0, sizeof(ColorContext));
    if (!This) return E_OUTOFMEMORY;

    This->IWICColorContext_iface.lpVtbl = &ColorContext_Vtbl;
    This->ref = 1;
    This->type = 0;
    This->profile = NULL;
    This->profile_len = 0;
    This->exif_color_space = ~0u;

    *colorcontext = &This->IWICColorContext_iface;

    return S_OK;
}
