/*              DirectDraw - IDirectPalette base interface
 *
 * Copyright 1997-2000 Marcus Meissner
 * Copyright 2000-2001 TransGaming Technologies Inc.
 * Copyright 2006 Stefan Dösinger 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 "winerror.h"
#include "wine/debug.h"

#include <string.h>

#include "wined3d_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(d3d);

#define SIZE_BITS (WINEDDPCAPS_1BIT | WINEDDPCAPS_2BIT | WINEDDPCAPS_4BIT | WINEDDPCAPS_8BIT)

static HRESULT  WINAPI IWineD3DPaletteImpl_QueryInterface(IWineD3DPalette *iface, REFIID refiid, void **obj) {
    IWineD3DPaletteImpl *This = (IWineD3DPaletteImpl *)iface;
    TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);

    if (IsEqualGUID(refiid, &IID_IUnknown)
        || IsEqualGUID(refiid, &IID_IWineD3DPalette)) {
        *obj = iface;
        IWineD3DPalette_AddRef(iface);
        return S_OK;
    }
    else {
        *obj = NULL;
        return E_NOINTERFACE;
    }
}

static ULONG  WINAPI IWineD3DPaletteImpl_AddRef(IWineD3DPalette *iface) {
    IWineD3DPaletteImpl *This = (IWineD3DPaletteImpl *)iface;
    ULONG ref = InterlockedIncrement(&This->ref);

    TRACE("(%p)->() incrementing from %u.\n", This, ref - 1);

    return ref;
}

static ULONG  WINAPI IWineD3DPaletteImpl_Release(IWineD3DPalette *iface) {
    IWineD3DPaletteImpl *This = (IWineD3DPaletteImpl *)iface;
    ULONG ref = InterlockedDecrement(&This->ref);

    TRACE("(%p)->() decrementing from %u.\n", This, ref + 1);

    if (!ref) {
        DeleteObject(This->hpal);
        HeapFree(GetProcessHeap(), 0, This);
        return 0;
    }

    return ref;
}

/* Not called from the vtable */
DWORD IWineD3DPaletteImpl_Size(DWORD dwFlags) {
    switch (dwFlags & SIZE_BITS) {
        case WINEDDPCAPS_1BIT: return 2;
        case WINEDDPCAPS_2BIT: return 4;
        case WINEDDPCAPS_4BIT: return 16;
        case WINEDDPCAPS_8BIT: return 256;
        default:
            FIXME("Unhandled size bits %#x.\n", dwFlags & SIZE_BITS);
            return 256;
    }
}

static HRESULT  WINAPI IWineD3DPaletteImpl_GetEntries(IWineD3DPalette *iface, DWORD Flags, DWORD Start, DWORD Count, PALETTEENTRY *PalEnt) {
    IWineD3DPaletteImpl *This = (IWineD3DPaletteImpl *)iface;

    TRACE("(%p)->(%08x,%d,%d,%p)\n",This,Flags,Start,Count,PalEnt);

    if (Flags != 0) return WINED3DERR_INVALIDCALL; /* unchecked */
    if (Start + Count > IWineD3DPaletteImpl_Size(This->Flags))
        return WINED3DERR_INVALIDCALL;

    if (This->Flags & WINEDDPCAPS_8BITENTRIES)
    {
        unsigned int i;
        LPBYTE entry = (LPBYTE)PalEnt;

        for (i=Start; i < Count+Start; i++)
            *entry++ = This->palents[i].peRed;
    }
    else
        memcpy(PalEnt, This->palents+Start, Count * sizeof(PALETTEENTRY));

    return WINED3D_OK;
}

static HRESULT  WINAPI IWineD3DPaletteImpl_SetEntries(IWineD3DPalette *iface,
        DWORD Flags, DWORD Start, DWORD Count, const PALETTEENTRY *PalEnt)
{
    IWineD3DPaletteImpl *This = (IWineD3DPaletteImpl *)iface;
    IWineD3DResourceImpl *res;

    TRACE("(%p)->(%08x,%d,%d,%p)\n",This,Flags,Start,Count,PalEnt);
    TRACE("Palette flags: %#x\n", This->Flags);

    if (This->Flags & WINEDDPCAPS_8BITENTRIES) {
        unsigned int i;
        const BYTE* entry = (const BYTE*)PalEnt;

        for (i=Start; i < Count+Start; i++)
            This->palents[i].peRed = *entry++;
    }
    else {
        memcpy(This->palents+Start, PalEnt, Count * sizeof(PALETTEENTRY));

        /* When WINEDDCAPS_ALLOW256 isn't set we need to override entry 0 with black and 255 with white */
        if(!(This->Flags & WINEDDPCAPS_ALLOW256))
        {
            TRACE("WINEDDPCAPS_ALLOW256 set, overriding palette entry 0 with black and 255 with white\n");
            This->palents[0].peRed = 0;
            This->palents[0].peGreen = 0;
            This->palents[0].peBlue = 0;

            This->palents[255].peRed = 255;
            This->palents[255].peGreen = 255;
            This->palents[255].peBlue = 255;
        }

        if (This->hpal)
            SetPaletteEntries(This->hpal, Start, Count, This->palents+Start);
    }

#if 0
    /* Now, if we are in 'depth conversion mode', update the screen palette */
    /* FIXME: we need to update the image or we won't get palette fading. */
    if (This->ddraw->d->palette_convert != NULL)
        This->ddraw->d->palette_convert(palent,This->screen_palents,start,count);
#endif

    /* If the palette is attached to the render target, update all render targets */

    LIST_FOR_EACH_ENTRY(res, &This->wineD3DDevice->resources, IWineD3DResourceImpl, resource.resource_list_entry) {
        if(IWineD3DResource_GetType((IWineD3DResource *) res) == WINED3DRTYPE_SURFACE) {
            IWineD3DSurfaceImpl *impl = (IWineD3DSurfaceImpl *) res;
            if(impl->palette == This)
                IWineD3DSurface_RealizePalette((IWineD3DSurface *) res);
        }
    }

    return WINED3D_OK;
}

static HRESULT  WINAPI IWineD3DPaletteImpl_GetCaps(IWineD3DPalette *iface, DWORD *Caps) {
    IWineD3DPaletteImpl *This = (IWineD3DPaletteImpl *)iface;
    TRACE("(%p)->(%p)\n", This, Caps);

    *Caps = This->Flags;
    return WINED3D_OK;
}

static HRESULT  WINAPI IWineD3DPaletteImpl_GetParent(IWineD3DPalette *iface, IUnknown **Parent) {
    IWineD3DPaletteImpl *This = (IWineD3DPaletteImpl *)iface;
    TRACE("(%p)->(%p)\n", This, Parent);

    *Parent = This->parent;
    IUnknown_AddRef(This->parent);
    return WINED3D_OK;
}

const IWineD3DPaletteVtbl IWineD3DPalette_Vtbl =
{
    /*** IUnknown ***/
    IWineD3DPaletteImpl_QueryInterface,
    IWineD3DPaletteImpl_AddRef,
    IWineD3DPaletteImpl_Release,
    /*** IWineD3DPalette ***/
    IWineD3DPaletteImpl_GetParent,
    IWineD3DPaletteImpl_GetEntries,
    IWineD3DPaletteImpl_GetCaps,
    IWineD3DPaletteImpl_SetEntries
};
