/*
 * Copyright 2013 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 ColorTransform {
    IWICColorTransform IWICColorTransform_iface;
    LONG ref;
    IWICBitmapSource *dst;
} ColorTransform;

static inline ColorTransform *impl_from_IWICColorTransform(IWICColorTransform *iface)
{
    return CONTAINING_RECORD(iface, ColorTransform, IWICColorTransform_iface);
}

static HRESULT WINAPI ColorTransform_QueryInterface(IWICColorTransform *iface, REFIID iid,
    void **ppv)
{
    ColorTransform *This = impl_from_IWICColorTransform(iface);
    TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);

    if (!ppv) return E_INVALIDARG;

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

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

static ULONG WINAPI ColorTransform_AddRef(IWICColorTransform *iface)
{
    ColorTransform *This = impl_from_IWICColorTransform(iface);
    ULONG ref = InterlockedIncrement(&This->ref);

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

    return ref;
}

static ULONG WINAPI ColorTransform_Release(IWICColorTransform *iface)
{
    ColorTransform *This = impl_from_IWICColorTransform(iface);
    ULONG ref = InterlockedDecrement(&This->ref);

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

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

    return ref;
}

static HRESULT WINAPI ColorTransform_GetSize(IWICColorTransform *iface,
    UINT *puiWidth, UINT *puiHeight)
{
    ColorTransform *This = impl_from_IWICColorTransform(iface);
    TRACE("(%p,%p,%p)\n", iface, puiWidth, puiHeight);

    return IWICBitmapSource_GetSize(This->dst, puiWidth, puiHeight);
}

static HRESULT WINAPI ColorTransform_GetPixelFormat(IWICColorTransform *iface,
    WICPixelFormatGUID *pPixelFormat)
{
    ColorTransform *This = impl_from_IWICColorTransform(iface);
    TRACE("(%p,%p)\n", iface, pPixelFormat);

    return IWICBitmapSource_GetPixelFormat(This->dst, pPixelFormat);
}

static HRESULT WINAPI ColorTransform_GetResolution(IWICColorTransform *iface,
    double *pDpiX, double *pDpiY)
{
    ColorTransform *This = impl_from_IWICColorTransform(iface);
    TRACE("(%p,%p,%p)\n", iface, pDpiX, pDpiY);

    return IWICBitmapSource_GetResolution(This->dst, pDpiX, pDpiY);
}

static HRESULT WINAPI ColorTransform_CopyPalette(IWICColorTransform *iface,
    IWICPalette *pIPalette)
{
    ColorTransform *This = impl_from_IWICColorTransform(iface);
    TRACE("(%p,%p)\n", iface, pIPalette);

    return IWICBitmapSource_CopyPalette(This->dst, pIPalette);
}

static HRESULT WINAPI ColorTransform_CopyPixels(IWICColorTransform *iface,
    const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer)
{
    ColorTransform *This = impl_from_IWICColorTransform(iface);
    TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer);

    return IWICBitmapSource_CopyPixels(This->dst, prc, cbStride, cbBufferSize, pbBuffer);
}

static HRESULT WINAPI ColorTransform_Initialize(IWICColorTransform *iface,
    IWICBitmapSource *pIBitmapSource, IWICColorContext *pIContextSource,
    IWICColorContext *pIContextDest, REFWICPixelFormatGUID pixelFmtDest)
{
    ColorTransform *This = impl_from_IWICColorTransform(iface);
    IWICBitmapSource *dst;
    HRESULT hr;

    TRACE("(%p,%p,%p,%p,%s)\n", iface, pIBitmapSource, pIContextSource,
          pIContextDest, debugstr_guid(pixelFmtDest));

    FIXME("ignoring color contexts\n");

    hr = WICConvertBitmapSource(pixelFmtDest, pIBitmapSource, &dst);
    if (FAILED(hr)) return hr;

    if (This->dst) IWICBitmapSource_Release(This->dst);
    This->dst = dst;
    return S_OK;
}

static const IWICColorTransformVtbl ColorTransform_Vtbl = {
    ColorTransform_QueryInterface,
    ColorTransform_AddRef,
    ColorTransform_Release,
    ColorTransform_GetSize,
    ColorTransform_GetPixelFormat,
    ColorTransform_GetResolution,
    ColorTransform_CopyPalette,
    ColorTransform_CopyPixels,
    ColorTransform_Initialize
};

HRESULT ColorTransform_Create(IWICColorTransform **colortransform)
{
    ColorTransform *This;

    if (!colortransform) return E_INVALIDARG;

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

    This->IWICColorTransform_iface.lpVtbl = &ColorTransform_Vtbl;
    This->ref = 1;
    This->dst = NULL;

    *colortransform = &This->IWICColorTransform_iface;

    return S_OK;
}
