/*
 * Copyright 2013 Nikolay Sivov 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 <stdarg.h>

#define COBJMACROS

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

#include "wincodecs_private.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);

typedef struct BitmapClipper {
    IWICBitmapClipper IWICBitmapClipper_iface;
    LONG ref;
    IWICBitmapSource *source;
    WICRect rect;
    CRITICAL_SECTION lock; /* must be held when initialized */
} BitmapClipper;

static inline BitmapClipper *impl_from_IWICBitmapClipper(IWICBitmapClipper *iface)
{
    return CONTAINING_RECORD(iface, BitmapClipper, IWICBitmapClipper_iface);
}

static HRESULT WINAPI BitmapClipper_QueryInterface(IWICBitmapClipper *iface, REFIID iid,
    void **ppv)
{
    BitmapClipper *This = impl_from_IWICBitmapClipper(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_IWICBitmapClipper, iid))
    {
        *ppv = &This->IWICBitmapClipper_iface;
    }
    else
    {
        *ppv = NULL;
        return E_NOINTERFACE;
    }

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

static ULONG WINAPI BitmapClipper_AddRef(IWICBitmapClipper *iface)
{
    BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
    ULONG ref = InterlockedIncrement(&This->ref);

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

    return ref;
}

static ULONG WINAPI BitmapClipper_Release(IWICBitmapClipper *iface)
{
    BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
    ULONG ref = InterlockedDecrement(&This->ref);

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

    if (ref == 0)
    {
        This->lock.DebugInfo->Spare[0] = 0;
        DeleteCriticalSection(&This->lock);
        if (This->source) IWICBitmapSource_Release(This->source);
        HeapFree(GetProcessHeap(), 0, This);
    }

    return ref;
}

static HRESULT WINAPI BitmapClipper_GetSize(IWICBitmapClipper *iface,
    UINT *width, UINT *height)
{
    BitmapClipper *This = impl_from_IWICBitmapClipper(iface);

    TRACE("(%p,%p,%p)\n", iface, width, height);

    if (!width || !height)
        return E_INVALIDARG;

    if (!This->source)
        return WINCODEC_ERR_WRONGSTATE;

    *width = This->rect.Width;
    *height = This->rect.Height;

    return S_OK;
}

static HRESULT WINAPI BitmapClipper_GetPixelFormat(IWICBitmapClipper *iface,
    WICPixelFormatGUID *format)
{
    BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
    TRACE("(%p,%p)\n", iface, format);

    if (!format)
        return E_INVALIDARG;

    if (!This->source)
        return WINCODEC_ERR_WRONGSTATE;

    return IWICBitmapSource_GetPixelFormat(This->source, format);
}

static HRESULT WINAPI BitmapClipper_GetResolution(IWICBitmapClipper *iface,
    double *dpiX, double *dpiY)
{
    BitmapClipper *This = impl_from_IWICBitmapClipper(iface);

    TRACE("(%p,%p,%p)\n", iface, dpiX, dpiY);

    if (!dpiX || !dpiY)
        return E_INVALIDARG;

    if (!This->source)
        return WINCODEC_ERR_WRONGSTATE;

    return IWICBitmapSource_GetResolution(This->source, dpiX, dpiY);
}

static HRESULT WINAPI BitmapClipper_CopyPalette(IWICBitmapClipper *iface,
    IWICPalette *palette)
{
    BitmapClipper *This = impl_from_IWICBitmapClipper(iface);

    TRACE("(%p,%p)\n", iface, palette);

    if (!palette)
        return E_INVALIDARG;

    if (!This->source)
        return WINCODEC_ERR_WRONGSTATE;

    return IWICBitmapSource_CopyPalette(This->source, palette);
}

static HRESULT WINAPI BitmapClipper_CopyPixels(IWICBitmapClipper *iface,
    const WICRect *rc, UINT stride, UINT buffer_size, BYTE *buffer)
{
    BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
    WICRect rect;

    TRACE("(%p,%p,%u,%u,%p)\n", iface, rc, stride, buffer_size, buffer);

    if (!This->source)
        return WINCODEC_ERR_WRONGSTATE;

    if (rc)
    {
        rect = *rc;

        /* transform to source coordinates */
        rect.X += This->rect.X;
        rect.Y += This->rect.Y;

        if ((rect.X + rect.Width > This->rect.X + This->rect.Width) ||
            (rect.Y + rect.Height > This->rect.Y + This->rect.Height))
            return E_INVALIDARG;

        rc = &rect;
    }
    else
        rc = &This->rect;

    return IWICBitmapSource_CopyPixels(This->source, rc, stride, buffer_size, buffer);
}

static HRESULT WINAPI BitmapClipper_Initialize(IWICBitmapClipper *iface,
    IWICBitmapSource *source, const WICRect *rc)
{
    BitmapClipper *This = impl_from_IWICBitmapClipper(iface);
    UINT width, height;
    HRESULT hr = S_OK;

    TRACE("(%p,%p,%p)\n", iface, source, rc);

    EnterCriticalSection(&This->lock);

    if (This->source)
    {
        hr = WINCODEC_ERR_WRONGSTATE;
        goto end;
    }

    hr = IWICBitmapSource_GetSize(source, &width, &height);
    if (FAILED(hr)) goto end;

    if  ((rc->X + rc->Width > width) || (rc->Y + rc->Height > height))
    {
        hr = E_INVALIDARG;
        goto end;
    }

    This->rect = *rc;
    This->source = source;
    IWICBitmapSource_AddRef(This->source);

end:
    LeaveCriticalSection(&This->lock);

    return hr;
}

static const IWICBitmapClipperVtbl BitmapClipper_Vtbl = {
    BitmapClipper_QueryInterface,
    BitmapClipper_AddRef,
    BitmapClipper_Release,
    BitmapClipper_GetSize,
    BitmapClipper_GetPixelFormat,
    BitmapClipper_GetResolution,
    BitmapClipper_CopyPalette,
    BitmapClipper_CopyPixels,
    BitmapClipper_Initialize
};

HRESULT BitmapClipper_Create(IWICBitmapClipper **clipper)
{
    BitmapClipper *This;

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

    This->IWICBitmapClipper_iface.lpVtbl = &BitmapClipper_Vtbl;
    This->ref = 1;
    This->source = NULL;
    InitializeCriticalSection(&This->lock);
    This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BitmapClipper.lock");

    *clipper = &This->IWICBitmapClipper_iface;

    return S_OK;
}
