#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#include "osd.h"
#include "defines.h"
#include "screen.h"

#include "LogMsg.h"

#define DEPTH  4
#define COLORS 1<<DEPTH

#if VDRVERSNUM < 10307
	#define COLOR(R,G,B,A) (R+(G<<8)+(B<<16)+(A<<24))
	#define PALETTE(I)     ((eDvbColor)colortable[I])
#else
	#define COLOR(R,G,B,A) (B+(G<<8)+(R<<16)+(A<<24))
	#define PALETTE(I)     ((tColor)colortable[I])
#endif

namespace Scr {

#if VDRVERSNUM < 10307
static cOsdBase    *screen = NULL;
#else
static cOsd        *screen = NULL;
#endif

static int W, H, colortable[COLORS], *shadow = NULL;

static int palette(int pal)
{
	switch (pal)
	{
		case PAL_VDR:
			colortable[0]  = COLOR(0x00, 0x00, 0x00, 0x7F); // Background
			colortable[1]  = COLOR(0xFC, 0xFC, 0xFC, 0xFF); // White
			colortable[2]  = COLOR(0xFC, 0x14, 0x14, 0xFF); // Red
			colortable[3]  = COLOR(0x00, 0xE0, 0xE0, 0xFF); // Cyan
			colortable[4]  = COLOR(0xB0, 0x00, 0xFC, 0xFF); // Magenta
			colortable[5]  = COLOR(0x24, 0xFC, 0x24, 0xFF); // Green
			colortable[6]  = COLOR(0x00, 0x00, 0xFC, 0xFF); // Blue
			colortable[7]  = COLOR(0xFC, 0xC0, 0x24, 0xFF); // Yellow
			colortable[8]  = COLOR(0xC0, 0xA0, 0x00, 0xFF); // Orange
			colortable[9]  = COLOR(0xFF, 0xA0, 0x00, 0xFF); // Orange2
			colortable[10] = COLOR(0xF0, 0x80, 0x80, 0xFF); // Pink
			colortable[11] = COLOR(0x00, 0xFF, 0xFF, 0xFF); // Cyan2
			colortable[12] = COLOR(0xFF, 0x00, 0xFF, 0xFF); // Purple2
			colortable[13] = COLOR(0x00, 0xFF, 0x00, 0xFF); // Green2
			colortable[14] = COLOR(0x00, 0xA0, 0xFF, 0xFF); // Blue2
			colortable[15] = COLOR(0x00, 0x00, 0x00, 0xFF); // Black
		break;
		case PAL_C64:
			colortable[0]  = COLOR(0x00, 0x00, 0x00, 0x7F); // Background
			colortable[1]  = COLOR(0xFF, 0xFF, 0xFF, 0xFF); // White
			colortable[2]  = COLOR(0xF0, 0x00, 0x00, 0xFF); // Red
			colortable[3]  = COLOR(0x00, 0xF0, 0xF0, 0xFF); // Cyan
			colortable[4]  = COLOR(0x60, 0x00, 0x60, 0xFF); // Purple
			colortable[5]  = COLOR(0x00, 0xA0, 0x00, 0xFF); // Green
			colortable[6]  = COLOR(0x00, 0x00, 0xF0, 0xFF); // Blue
			colortable[7]  = COLOR(0xD0, 0xD0, 0x00, 0xFF); // Yellow
			colortable[8]  = COLOR(0xC0, 0xA0, 0x00, 0xFF); // Orange
			colortable[9]  = COLOR(0xFF, 0xA0, 0x00, 0xFF); // Orange2
			colortable[10] = COLOR(0xF0, 0x80, 0x80, 0xFF); // Pink
			colortable[11] = COLOR(0x00, 0xFF, 0xFF, 0xFF); // Cyan2
			colortable[12] = COLOR(0xFF, 0x00, 0xFF, 0xFF); // Purple2
			colortable[13] = COLOR(0x00, 0xFF, 0x00, 0xFF); // Green2
			colortable[14] = COLOR(0x00, 0xA0, 0xFF, 0xFF); // Blue2
			colortable[15] = COLOR(0x00, 0x00, 0x00, 0xFF); // Black
		break;
	}

	for (int i=0; i<COLORS; i++)
	{
#if VDRVERSNUM < 10307
		if (screen)
			screen->AddColor(PALETTE(i));
#else
		if (screen) {
			screen->GetBitmap(0)->SetColor(i, PALETTE(i));
		}
#endif
	}

	return (0);
}

int
pixel(int x, int y, int idx)
{
	if (!screen || x<0 || x>=W || y<0 || y>=H || idx<0 || idx>=COLORS)
	{
		return (-1);
	}
	if (shadow) shadow[W*y+x] = idx;

#if VDRVERSNUM < 10307
	screen->Fill(x, y, x, y, PALETTE(idx));
#else
	screen->DrawPixel(x, y, PALETTE(idx));
#endif


	return (0);
}


void initOSD(cOsd **ppOsd,int *sizeX,int *sizeY)
{
	int n=0;
	eOsdError Result;
	cOsd *pOsd = *ppOsd;

	pOsd = cOsdProvider::NewOsd(60,50);
	if(pOsd != NULL)
	{
		tArea Areas[] = { { 0, 0, 560, 280, 2 } };
		if (pOsd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
		{
			Result = pOsd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
		}
	    else
		{
			do
			{
				printf("cScOsd::Show() try little :");
				if(n==0)
					{ 	Areas[0].x2 -= 1;n=1; }
				else
					{ 	Areas[0].y2 -= 1;n=0; }

				Result = pOsd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea));
				printf("Areas : 0,0,%d,%d : %d \n",Areas[0].x2,Areas[0].y2,Result);
			}
			while( Result != oeOk && Areas[0].y2>0);

        	printf("cScOsd::CanHandleAreas() return oeOk !\n");

        	Result = pOsd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
    	}

	    printf("cScOsd::Show() SetAreas return : %d (oeOk = %d )\n",Result,oeOk);
	    switch(Result)
    	{
	    	case oeOk:				printf("oeOk\n");break;
			case oeTooManyAreas:	printf("oeTooManyAreas\n");break;
	        case oeTooManyColors:	printf("oeTooManyColors\n");break;
	        case oeBppNotSupported:	printf("oeBppNotSupported\n");break;
	        case oeAreasOverlap:	printf("oeAreasOverlap\n");break;
	        case oeWrongAlignment:	printf("oeWrongAlignment\n");break;
	        case oeOutOfMemory:		printf("oeOutOfMemory\n");break;
	        case oeUnknown:			printf("oeUnknown\n");break;
		}

	    printf("cScOsd::Show() pOsd->DrawRectangle\n");
	    pOsd->DrawRectangle(0, 0, Areas[0].x2, Areas[0].y2, clrWhite);
    	pOsd->DrawRectangle(2, 2, Areas[0].x2-4, Areas[0].y2-4, clrTransparent);
     	*sizeX = Areas[0].x2;
     	*sizeY = Areas[0].y2;

	    printf("cScOsd::Show() pOsd->Flush\n");
     	pOsd->Flush();
     }

     printf("cScOsd::Show() pOsd :%x\n",pOsd);

	*ppOsd = pOsd;
}



int
open(int x, int y, int w, int h)
{
	if (screen)
		return (-1);

	if (x<0 || x>=800 || y<0 || y>=600)
		return (-1);

	if (w<=0 || w>800 || h<=0 || h>600)
		return (-1);

	W = w; H = h;

#if VDRVERSNUM < 10307
	tWindowHandle win;

	if (!(screen = cOsd::OpenRaw(x, y))) {
		if (!(screen = cOsd::OpenRaw(x, y))) {
			return (-1);
		}
	}
	win = screen->Create(0, 0, w, h, DEPTH);
	palette(PAL_VDR);
	screen->Show(win);
	screen->Flush();
#else

	printf("cScOsd::Show() screen :%x\n",screen);
	printf("cScOsd::Show() &screen :%x\n",&screen);

	initOSD(&screen,&W,&H);

//	tArea win = { 0, 0, w-1, h-1, DEPTH };
/*
	if (!(screen = cOsdProvider::NewOsd(x, y)))
	{
		if (!(screen = cOsdProvider::NewOsd(x, y)))
		{
			return(-1);
		}
	}
	Result = screen->SetAreas(&win, 1);
    switch(Result)
	{
    	case oeOk:				printf("oeOk\n");break;
		case oeTooManyAreas:	printf("oeTooManyAreas\n");break;
        case oeTooManyColors:	printf("oeTooManyColors\n");break;
        case oeBppNotSupported:	printf("oeBppNotSupported\n");break;
        case oeAreasOverlap:	printf("oeAreasOverlap\n");break;
        case oeWrongAlignment:	printf("oeWrongAlignment\n");break;
        case oeOutOfMemory:		printf("oeOutOfMemory\n");break;
        case oeUnknown:			printf("oeUnknown\n");break;
	}
*/
	palette(PAL_VDR);
	printf("cScOsd::Show() screen :%x\n",screen);
	screen->Flush();
#endif


	LogMsg(LOGLEVEL_MAIN,"MlDkGUI : Scr::open  (%d,%d)\n",H,W);


	if (!(shadow = (int *)calloc(W*H, sizeof (int))))
	{
		return (-1);
	}

		LogMsg(LOGLEVEL_MAIN,"MlDkGUI : Scr::open : calloc Ok \n");

	for (int y1=0; y1<H; y1++)
	{
		for (int x=0; x<W; x++)
			pixel(x, y1, 1);
	}
	return (0);
}

int clear(void)
{

	for (int y1=0; y1<H; y1++)
    {
		for (int x=0; x<W; x++)
            pixel(x, y1, 0);
	}
    return (0);
}

int close(void)
{
	if (screen)
	{
		free(shadow);
		delete (screen);
		screen = NULL;
		shadow = NULL;
		return (0);
	}
	return (-1);
}

int
update(void)
{
	if (screen)
	{
		screen->Flush();
		fprintf(stderr,"screen->Flush\n");
		return (0);
	}
	return (-1);
}

int
pixel(int x, int y)
{
	if (shadow)
		return (shadow[W*y+x]);
	return (-1);
}

int
width(void)
{
	if (screen)
		return (W);
	return (-1);
}

int
height(void)
{
	if (screen)
		return (H);
	return (-1);
}

} // namespace
