/*		DirectDraw - IDirectPalette base interface
 *
 * Copyright 1997-2000 Marcus Meissner
 * Copyright 2000-2001 TransGaming Technologies Inc.
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "config.h"
#include "winerror.h"
#include "wine/debug.h"

#include <assert.h>
#include <string.h>

#include "ddraw_private.h"
#include "dpalette/main.h"
#include "ddraw/main.h"

WINE_DEFAULT_DEBUG_CHANNEL(ddraw);

#define SIZE_BITS (DDPCAPS_1BIT | DDPCAPS_2BIT | DDPCAPS_4BIT | DDPCAPS_8BIT)

/* For unsigned x. 0 is not a power of 2. */
#define IS_POW_2(x) (((x) & ((x) - 1)) == 0)

static ICOM_VTABLE(IDirectDrawPalette) DDRAW_Main_Palette_VTable;

/******************************************************************************
 *			IDirectDrawPalette
 */
HRESULT Main_DirectDrawPalette_Construct(IDirectDrawPaletteImpl* This,
					 IDirectDrawImpl* pDD, DWORD dwFlags)
{
    if (!IS_POW_2(dwFlags & SIZE_BITS)) return DDERR_INVALIDPARAMS;

    if (dwFlags & DDPCAPS_8BITENTRIES)
	WARN("creating palette with 8 bit entries\n");

    This->palNumEntries = Main_DirectDrawPalette_Size(dwFlags);
    This->ref = 1;

    This->local.lpGbl = &This->global;
    This->local.lpDD_lcl = &pDD->local;
    This->global.lpDD_lcl = &pDD->local;
    This->global.dwProcessId = GetCurrentProcessId();
    This->global.dwFlags = dwFlags;

    This->final_release = Main_DirectDrawPalette_final_release;
    ICOM_INIT_INTERFACE(This, IDirectDrawPalette, DDRAW_Main_Palette_VTable);

    /* we could defer hpal creation until we need it,
     * but does anyone have a case where it would be useful? */
    This->hpal = CreatePalette((const LOGPALETTE*)&(This->palVersion));

    Main_DirectDraw_AddPalette(pDD, This);

    return DD_OK;
}

HRESULT
Main_DirectDrawPalette_Create(IDirectDrawImpl* pDD, DWORD dwFlags,
			      LPDIRECTDRAWPALETTE* ppPalette,
			      LPUNKNOWN pUnkOuter)
{
    IDirectDrawPaletteImpl* This;
    HRESULT hr;

    if (pUnkOuter != NULL)
	return CLASS_E_NOAGGREGATION; /* unchecked */

    This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
    if (This == NULL) return E_OUTOFMEMORY;

    hr = Main_DirectDrawPalette_Construct(This, pDD, dwFlags);
    if (FAILED(hr))
	HeapFree(GetProcessHeap(), 0, This);
    else
	*ppPalette = ICOM_INTERFACE(This, IDirectDrawPalette);

    return hr;
}

DWORD Main_DirectDrawPalette_Size(DWORD dwFlags)
{
    switch (dwFlags & SIZE_BITS)
    {
    case DDPCAPS_1BIT: return 2;
    case DDPCAPS_2BIT: return 4;
    case DDPCAPS_4BIT: return 16;
    case DDPCAPS_8BIT: return 256;
    default: assert(0); return 256;
    }
}

HRESULT WINAPI
Main_DirectDrawPalette_GetEntries(LPDIRECTDRAWPALETTE iface, DWORD dwFlags,
				  DWORD dwStart, DWORD dwCount,
				  LPPALETTEENTRY palent)
{
    ICOM_THIS(IDirectDrawPaletteImpl,iface);

    TRACE("(%p)->GetEntries(%08lx,%ld,%ld,%p)\n",This,dwFlags,dwStart,dwCount,
	  palent);

    if (dwFlags != 0) return DDERR_INVALIDPARAMS; /* unchecked */
    if (dwStart + dwCount > Main_DirectDrawPalette_Size(This->global.dwFlags))
	return DDERR_INVALIDPARAMS;

    if (This->global.dwFlags & DDPCAPS_8BITENTRIES)
    {
	int i;
	LPBYTE entry = (LPBYTE)palent;

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

    return DD_OK;
}

HRESULT WINAPI
Main_DirectDrawPalette_SetEntries(LPDIRECTDRAWPALETTE iface, DWORD dwFlags,
				  DWORD dwStart, DWORD dwCount,
				  LPPALETTEENTRY palent)
{
    ICOM_THIS(IDirectDrawPaletteImpl,iface);

    TRACE("(%p)->SetEntries(%08lx,%ld,%ld,%p)\n",This,dwFlags,dwStart,dwCount,
	  palent);

    if (This->global.dwFlags & DDPCAPS_8BITENTRIES)
    {
	int i;
	const BYTE* entry = (const BYTE*)palent;

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

	if (This->hpal)
	    SetPaletteEntries(This->hpal, dwStart, dwCount, This->palents+dwStart);

	if (This->global.dwFlags & DDPCAPS_PRIMARYSURFACE) {
	    /* update physical palette */
	    LPDIRECTDRAWSURFACE7 psurf = NULL;
	    IDirectDraw7_GetGDISurface(ICOM_INTERFACE(This->ddraw_owner,IDirectDraw7), &psurf);
	    if (psurf) {
		IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl,
							   IDirectDrawSurface7, psurf);
		surf->update_palette(surf, This, dwStart, dwCount, palent);
		IDirectDrawSurface7_Release(psurf);
	    }
	    else ERR("can't find GDI surface!!\n");
	}
    }

#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

    return DD_OK;
}

void Main_DirectDrawPalette_final_release(IDirectDrawPaletteImpl* This)
{
    Main_DirectDraw_RemovePalette(This->ddraw_owner, This);

    if (This->hpal) DeleteObject(This->hpal);
}

static void Main_DirectDrawPalette_Destroy(IDirectDrawPaletteImpl* This)
{
    This->final_release(This);

    if (This->private != This+1)
	HeapFree(GetProcessHeap(), 0, This->private);

    HeapFree(GetProcessHeap(),0,This);
}

void Main_DirectDrawPalette_ForceDestroy(IDirectDrawPaletteImpl* This)
{
    WARN("deleting palette %p with refcnt %lu\n", This, This->ref);
    Main_DirectDrawPalette_Destroy(This);
}

ULONG WINAPI
Main_DirectDrawPalette_Release(LPDIRECTDRAWPALETTE iface)
{
    ICOM_THIS(IDirectDrawPaletteImpl,iface);
    TRACE("(%p)->() decrementing from %lu.\n", This, This->ref );

    if (!--This->ref)
    {
	Main_DirectDrawPalette_Destroy(This);
	return 0;
    }

    return This->ref;
}

ULONG WINAPI Main_DirectDrawPalette_AddRef(LPDIRECTDRAWPALETTE iface) {
    ICOM_THIS(IDirectDrawPaletteImpl,iface);
    TRACE("(%p)->() incrementing from %lu.\n", This, This->ref );
    return ++This->ref;
}

HRESULT WINAPI
Main_DirectDrawPalette_Initialize(LPDIRECTDRAWPALETTE iface,
				  LPDIRECTDRAW ddraw, DWORD dwFlags,
				  LPPALETTEENTRY palent)
{
    ICOM_THIS(IDirectDrawPaletteImpl,iface);
    TRACE("(%p)->(%p,%ld,%p)\n", This, ddraw, dwFlags, palent);
    return DDERR_ALREADYINITIALIZED;
}

HRESULT WINAPI
Main_DirectDrawPalette_GetCaps(LPDIRECTDRAWPALETTE iface, LPDWORD lpdwCaps)
{
   ICOM_THIS(IDirectDrawPaletteImpl,iface);
   TRACE("(%p)->(%p)\n",This,lpdwCaps);

   *lpdwCaps = This->global.dwFlags;

   return DD_OK;
}

HRESULT WINAPI
Main_DirectDrawPalette_QueryInterface(LPDIRECTDRAWPALETTE iface,
				      REFIID refiid, LPVOID *obj)
{
    ICOM_THIS(IDirectDrawPaletteImpl,iface);
    TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);

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

static ICOM_VTABLE(IDirectDrawPalette) DDRAW_Main_Palette_VTable =
{
    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
    Main_DirectDrawPalette_QueryInterface,
    Main_DirectDrawPalette_AddRef,
    Main_DirectDrawPalette_Release,
    Main_DirectDrawPalette_GetCaps,
    Main_DirectDrawPalette_GetEntries,
    Main_DirectDrawPalette_Initialize,
    Main_DirectDrawPalette_SetEntries
};
