/*
  Copyright (c) 2007-2013, John Ryland
 */
#include <oslayer.h>
#include <corelayer.h>
#include <keypad.h>
#include <image.h>
#include <screen.h>
#include <font.h>
#include <sound.h>

short *fbptr;
short rTab[256];
short gTab[256];
short bTab[256];
unsigned char offscreenBufferPixels[320*240*sizeof(short)];


void initTables()
{
	int r, g, b, y;
	for (r = 0; r < 256; r++)
		rTab[r] = (r>>3)<<11;
	for (g = 0; g < 256; g++)
		gTab[g] = (g>>2)<<5;
	for (b = 0; b < 256; b++)
		bTab[b] = b>>3;
}


void fadeTests(Image screen)
{
	int fadeItem = 0;
	int cycleId = timerQueue_CreateTimer(50, 1, "cycle");
	while (fadeItem >= 0) {
		Event ev = getNextEvent();
		if (ev.type == KeyEventType) {
			fadeItem = -2;
		} else if ( ev.type == TimerEventType ) {
			if ( fadeItem < 16 )
				fillImage(screen, rTab[fadeItem<<4]);
			else if ( fadeItem < 32 )
				fillImage(screen, gTab[(fadeItem-16)<<4]);
			else if ( fadeItem < 48 )
				fillImage(screen, bTab[(fadeItem-32)<<4]);
			else if ( fadeItem < 64 ) {
				int t = fadeItem-48;
				fillImage(screen, rTab[t<<4] | gTab[t<<4] | bTab[t<<4]);
			} else
				fadeItem = -2;
			fadeItem++;
		}
	}
	timerQueue_DeleteTimer(cycleId);
}


/*
Menus
-----
whatsup
communication.png
							Skype
							Google Talk
							Yahoo! Messenger
							Ad Hoc Application
*/

#include <menus.h>

int lastMenuIndex = 1; // Home
int menuIndex = 1; // Home


Font fontA, fontB;


void drawListText(Image *dst, int x, int y, int offX, int offY, int width, int height, int menuIdx)
{
/*
	Image messageImage = openImageFile("pics/listText.map");
	blitImage(dst, x, y, &messageImage, offX, offY, width, height);
	closeImageFile(messageImage);
*/
	Font font3 = (x == 105) ? fontB : fontA;
	int h = (height < 0) ? 21 * 9 : height;
	int i;
	int firstY = y - 2;
	int lastY = y + h - 20;
	int itemY = y - offY;

	Menu *menu = menuArray[menuIdx];
	MenuItem *items = menu->items;

	x -= offX;

	for (i = 0; i < menu->itemCount; i++) {
		if ( itemY < lastY && itemY > firstY ) {
			Image icon;

			if ( !items[i].imagesLoaded ) {
				char buf[128];
				int len = strLength(items[i].icon);
				memCopy(buf, "pics/Medium/40x40_", 18);
				memCopy(buf+18, items[i].icon, len);
				memCopy(buf+18+len, ".map", 5);
//				strPrint(buf);
//				strPrint("\n");
				items[i].imageMedium = openImageFile(buf);
				memCopy(buf, "pics/Small/18x18_", 17);
				memCopy(buf+17, items[i].icon, len);
				memCopy(buf+17+len, ".map", 5);
//				strPrint(buf);
//				strPrint("\n");
				items[i].imageSmall = openImageFile(buf);
				items[i].imagesLoaded = 1;
			}

//			icon = (x == 105) ? openImageFile("pics/iconSel.map") : openImageFile("pics/icon.map");

			if ( x == 105 ) {
				icon = items[i].imageMedium;
				drawText(dst, x+7+11, itemY-3, font3, items[i].text);
				blitImage(dst, x-15-12, itemY+2-11, &icon, 0, 0, -1, -1);
			} else {
				icon = items[i].imageSmall;
				drawText(dst, x+7+5, itemY, font3, items[i].text);
				blitImage(dst, x-10, itemY+2, &icon, 0, 0, -1, -1);
			}
//			closeImageFile(icon);
		}
		itemY += 21;
	}
}

unsigned itemForY(unsigned y)
{
	if (y-1)
		return (y-1) / 21;
	return 0;
}

void updateMenuOnSelect(int y)
{
	Menu *menu = menuArray[menuIndex];
	const MenuItem *items = menu->items;
	int t = items[itemForY(y)].actionValue;
	if (t) {
		lastMenuIndex = menuIndex;
		menuIndex = t;
	}
}

void updateMenuOnBack()
{
	lastMenuIndex = menuIndex;
	menuIndex = 1;
}

typedef struct {
	int	menuIndex;
	int	lastMenuIndex;
	int	blahY;
	int	blahYRem;
	int	blahYNext;
	int	scrollY;
	int	focused;
	int	select;
	int	back;
	Image   listFocus;
	Image   wallpaper;
	Image   screen;
	Image   offscreenBuffer;
} MenuList;


void repaintMenu(MenuList *list)
{
	int tb = list->select / 2;
	int ts = list->back / 2;

	blitImage(&list->offscreenBuffer, 80, 0, &list->wallpaper, 80, 0, -1, -1);
	blitImage(&list->offscreenBuffer, 80, 0, &list->listFocus, 80, 0, -1, -1);

	ts = (ts > 75) ? 75 : ts;
	tb = (tb-75 < 0) ? 0 : tb-75;
	if ( ts ) {
		drawListText(&list->offscreenBuffer, 100,   0, 75-ts, list->blahYNext-52, -1, 52, menuIndex);
		drawListText(&list->offscreenBuffer, 100, 100, 75-ts, list->blahYNext+20, -1, -1, menuIndex);
	}
	if ( tb != 75 ) {
		drawListText(&list->offscreenBuffer, 100+tb,   0, 0, list->blahYNext-52, -1, 52, menuIndex);
		drawListText(&list->offscreenBuffer, 100+tb, 100, 0, list->blahYNext+20, -1, -1, menuIndex);
	}
	if ( !ts && (tb == 75) ) {
		drawListText(&list->offscreenBuffer, 100+ts,   0, 75-tb, list->blahY-52, -1, 52, menuIndex);
		drawListText(&list->offscreenBuffer, 100+ts, 100, 75-tb, list->blahY+20, -1, -1, menuIndex);
	}
	if ( list->select == 300 && !list->back ) {
		if ( list->focused ) {
			drawListText(&list->offscreenBuffer, 105, 63, 0, list->blahY, -1, 20, menuIndex);
		} else {
			int t = list->blahY + list->blahYRem;
			drawListText(&list->offscreenBuffer, 100, 65, 0, t, -1, 30, menuIndex);
		}
	}

	/* Provides some clipping */
	blitImage(&list->offscreenBuffer, 0, 0, &list->wallpaper, 0, 0, 80, 240);
	blitImage(&list->offscreenBuffer, 0, 220, &list->wallpaper, 0, 220, -1, -1);
	blitImage(&list->offscreenBuffer, 0, 0, &list->listFocus, 0, 0, 80, 220);

	if ( !menuArray[menuIndex]->imageLoaded ) {
		Menu *menu = menuArray[menuIndex];
		char buf[128];
		Image icon;
		int len = strLength(menu->icon);
		memCopy(buf, "pics/menus/", 11);
		memCopy(buf+11, menu->icon, len);
		memCopy(buf+11+len, ".map", 5);
		//strPrint(buf);
		menuArray[menuIndex]->image = openImageFile(buf);
		//closeImageFile(icon);
		menuArray[menuIndex]->imageLoaded = 1;
	}

	if ( ts )
		blitImage(&list->offscreenBuffer, 3, 7, &menuArray[menuIndex]->image, 75-ts, 0, 2+ts, -1);
	if ( tb != 75 )
		blitImage(&list->offscreenBuffer, 3+tb, 7, &menuArray[menuIndex]->image, 0, 0, 77-tb, -1);
	if ( !ts && (tb == 75) )
		blitImage(&list->offscreenBuffer, 3+ts, 7, &menuArray[menuIndex]->image, 75-tb, 0, 2+tb-ts, -1);

	/*
	   small new focus, (new removed in list), rest scroll up
	   rest scrolls int to place
	   focus expands
	   (all are higher when scrolling up)
	 */
	blitScreen(list->screen.pixel_data, offscreenBufferPixels);
		strPrint("Here2\n");
}


void resetTimer(int *timerId, int timeout, int repeat, char *name)
{
	if ( *timerId ) 
		timerQueue_DeleteTimer(*timerId);
	*timerId = timerQueue_CreateTimer(timeout, repeat, name);
}

void deleteTimer(int *timerId)
{
	if (*timerId)
		timerQueue_DeleteTimer(*timerId);
	*timerId = 0;
}

int audio;
Sound sound;
void playBeep()
{
return;
	static int init = 0;
	if (!init) {
		sound = openSoundFile("sounds/listmove.wav");
		init = 1;
	}
	playSound(audio, &sound);
//	playSoundFile(audio, "sounds/listmove.wav");
}

int main()
{
	KeyEvent keyEv;
	TimerEvent timerEv;

	int leftId = 0;
	int rightId = 0;
	int upId = 0;
	int downId = 0;
	int highlightFocusId = 0;
	int upScrollId = 0;
	int downScrollId = 0;
	int autoRepeatScrollDownId = 0;
	int autoRepeatScrollUpId = 0;
	int selectId = 0;
	int backId = 0;

	MenuList listA;
	MenuList *list = &listA;

	Image messageImage = openImageFile("pics/listText.map");
	audio = openSound();

	fontA = openFont("fonts/Vera-12.map");
	fontB = openFont("fonts/Vera-14.map");

	list->blahY = 1+42;
	list->blahYNext = 1+42;
	list->blahYRem = 0;
	list->scrollY = 0;
	list->focused = 1;
	list->select = 300;
	list->back = 0;
	list->listFocus = openImageFile("pics/listFocus.map");
	list->wallpaper = openImageFile("pics/wallpaper.map");
	list->screen = openScreen();
	list->offscreenBuffer.width = 320;
	list->offscreenBuffer.height = 240;
	list->offscreenBuffer.bytes_per_pixel = 2;
	list->offscreenBuffer.pixel_data = offscreenBufferPixels;

	strPrint("SONY mylo lcd test\nVersion 0.02\nCopyright 2007 John Ryland\n");

	openKeypad();
	initTables();
	fadeTests(list->screen);

	timerQueue_CreateTimer(100, 0, "begin");

	while (1) {
		strPrint("waiting for next event\n");

		Event ev = getNextEvent();

		strPrint("getting next event\n");
		strPrintf("event type: %i\n", ev.type);

		messageImage.height = 21*menuArray[menuIndex]->itemCount;

		if (ev.type == KeyEventType) {
			keyEv = ev.event.keyEvent;
			strPrint("got ");
			if (keyEv.desc)
				strPrint(keyEv.desc);
			strPrintf(" key event (%i)\n", keyEv.code);
			if (keyEv.pressed) {
//				strPrint("Press event\n");
				//if (!strCompare(keyEv.desc,"Left")) {
				//} else
				if (!strCompare(keyEv.desc,"Right")) {

					if ( menuArray[menuIndex]->items[itemForY(list->blahY)].actionValue ) {
						playBeep();
						resetTimer(&selectId, 30, 1, "select");
						list->select = 300;
						if (list->blahYRem)
							list->blahY += list->blahYRem;
						list->blahYRem = 0;
						list->blahYNext = 1+42;
					}

				} else if (!strCompare(keyEv.desc,"Down")) {

					if ( list->blahY <= ((int)messageImage.height - 41) ) {
						playBeep();
						deleteTimer(&highlightFocusId);
						if ( !downScrollId )
							downScrollId = timerQueue_CreateTimer(5, 1, "down");
						if (list->blahYRem)
							list->blahY += list->blahYRem;
						list->blahY += 5;
						list->blahYRem = 16;
						list->scrollY = 1;
						list->focused = 0;

						downId = timerQueue_CreateTimer(250, 0, "down");
					}

				} else if (!strCompare(keyEv.desc,"Up")) {

					if ( list->blahY >= 22 ) {
						playBeep();
						deleteTimer(&highlightFocusId);
						if ( !upScrollId )
							upScrollId = timerQueue_CreateTimer(5, 1, "up");
						if (list->blahYRem)
							list->blahY += list->blahYRem;
						list->blahY -= 5;
						list->blahYRem = -16;
						list->scrollY = 1;
						list->focused = 0;

						upId = timerQueue_CreateTimer(250, 0, "up");
					}

				} else if (!strCompare(keyEv.desc,"Select")) {

					if ( menuArray[menuIndex]->items[itemForY(list->blahY)].actionValue ) {
						playBeep();
						resetTimer(&selectId, 30, 1, "select");
						list->select = 300;
						if (list->blahYRem)
							list->blahY += list->blahYRem;
						list->blahYRem = 0;
						list->blahYNext = 1+42;
					}

				//} else if (!strCompare(keyEv.desc,"Back")) {
				} else if (!strCompare(keyEv.desc,"Left")) {

					if ( menuIndex != 1 ) {
						playBeep();
						resetTimer(&backId, 30, 1, "back");
						list->back = 0;
						if (list->blahYRem)
							list->blahY += list->blahYRem;
						list->blahYRem = 0;
						list->blahYNext = 1+42;
					}

				}
			} else {
//				strPrint("Release event\n");
				if (!strCompare(keyEv.desc,"Left")) {
					deleteTimer(&leftId);
				} else if (!strCompare(keyEv.desc,"Right")) {
					deleteTimer(&rightId);
				} else if (!strCompare(keyEv.desc,"Down")) {
					if (autoRepeatScrollDownId) {
						Event ev;
						deleteTimer(&autoRepeatScrollDownId);
						ev.type = KeyEventType;
						ev.event.keyEvent.desc = "Down";
						ev.event.keyEvent.pressed = 1;
						eventQueue_AppendEvent(ev);
						ev.event.keyEvent.pressed = 0;
						eventQueue_AppendEvent(ev);
					}
					deleteTimer(&downId);
				} else if (!strCompare(keyEv.desc,"Up")) {
					if (autoRepeatScrollUpId) {
						Event ev;
						deleteTimer(&autoRepeatScrollUpId);
						ev.type = KeyEventType;
						ev.event.keyEvent.desc = "Up";
						ev.event.keyEvent.pressed = 1;
						eventQueue_AppendEvent(ev);
						ev.event.keyEvent.pressed = 0;
						eventQueue_AppendEvent(ev);
					}
					deleteTimer(&upId);
				}
			}
		}

		if ( ev.type == TimerEventType ) {
			strPrint("got timer event\n");
			timerEv = ev.event.timerEvent;
			if (timerEv.id == backId) {
				if ( !list->back )
					updateMenuOnBack(); // XXX
				list->back += 50;
				if ( list->back >= 300 ) {
					deleteTimer(&backId);
					list->back = 0;
					list->blahY = list->blahYNext;
				}
			} else if (timerEv.id == selectId) {
				if ( list->select == 300 )
					updateMenuOnSelect(list->blahY); // XXX
				list->select -= 50;
				if ( list->select <= 0 ) {
					deleteTimer(&selectId);
					list->select = 300;
					list->blahY = list->blahYNext;
				}
			} else if (timerEv.id == leftId) {
			} else if (timerEv.id == rightId) {
			} else if (timerEv.id == downId) {
				downId = 0;
				autoRepeatScrollDownId = timerQueue_CreateTimer(15, 1, "up");
			} else if (timerEv.id == upId) {
				upId = 0;
				autoRepeatScrollUpId = timerQueue_CreateTimer(15, 1, "up");
			} else if (timerEv.id == autoRepeatScrollDownId) {

				deleteTimer(&downScrollId);
				if ( list->blahY < ((int)messageImage.height - 61) ) {
					playBeep();
					list->blahY += 21;
					list->focused = 0;
				}

				if (list->blahYRem)
					list->blahY += list->blahYRem;
				list->blahYRem = 0;
				list->scrollY = 0;
				if ( list->blahY > ((int)messageImage.height - 61) ) {
					if (autoRepeatScrollDownId) {
						Event ev;
						deleteTimer(&autoRepeatScrollDownId);
						ev.type = KeyEventType;
						ev.event.keyEvent.desc = "Down";
						ev.event.keyEvent.pressed = 1;
						eventQueue_AppendEvent(ev);
						ev.event.keyEvent.pressed = 0;
						eventQueue_AppendEvent(ev);
					} else {
						resetTimer(&highlightFocusId, 100, 0, "focus");
					}
					deleteTimer(&downId);
				}

			} else if (timerEv.id == autoRepeatScrollUpId) {

				deleteTimer(&upScrollId);
				if ( list->blahY >= 23 ) {
					playBeep();
					list->blahY -= 21;
					list->focused = 0;
				}
				if (list->blahYRem)
					list->blahY += list->blahYRem;
				list->blahYRem = 0;
				list->scrollY = 0;
				if ( list->blahY <= 23 ) {
					if (autoRepeatScrollUpId) {
						Event ev;
						deleteTimer(&autoRepeatScrollUpId);
						ev.type = KeyEventType;
						ev.event.keyEvent.desc = "Up";
						ev.event.keyEvent.pressed = 1;
						eventQueue_AppendEvent(ev);
						ev.event.keyEvent.pressed = 0;
						eventQueue_AppendEvent(ev);
					} else {
						resetTimer(&highlightFocusId, 100, 0, "focus");
					}
					deleteTimer(&upId);
				}
			} else if (timerEv.id == highlightFocusId) {
				list->focused = 1;
				highlightFocusId = 0;
				timerQueue_CreateTimer(10, 0, "focus");
			} else if (timerEv.id == downScrollId) {
				list->scrollY++;
				if ( list->blahYRem == 16 ) {
					list->blahY += 5;
					list->blahYRem -= 5;
				} else {
					list->blahY += list->blahYRem;
					list->blahYRem = 0;
					resetTimer(&highlightFocusId, 100, 0, "focus");
				}
				if (list->blahYRem == 0) {
					deleteTimer(&downScrollId);
				}
			} else if (timerEv.id == upScrollId) {
				list->scrollY++;
				if ( list->blahYRem == -16 ) {
					list->blahY -= 5;
					list->blahYRem += 5;
				} else {
					list->blahY += list->blahYRem;
					list->blahYRem = 0;
					resetTimer(&highlightFocusId, 100, 0, "focus");
				}
				if (list->blahYRem == 0) {
					deleteTimer(&upScrollId);
				}
			}
		}

		strPrint("Here\n");
		repaintMenu(list);

	}

	closeFont(fontA);
	closeFont(fontB);
	closeScreen(list->screen);
	closeSound(audio);

	return 0;
}



