#include <stdio.h>
#include <stdint.h>

#include "oswald.h"
#include "oswald_main.h"
#include "Fonts.h"
#include "LcdDisplay.h"
#include "oswald_hal.h"

#include "oswald_watch_faces.h"

#include "battery0_icon.xbm"
#include "battery25_icon.xbm"
#include "battery50_icon.xbm"
#include "battery75_icon.xbm"
#include "battery100_icon.xbm"
#include "charger_icon.xbm"
#include "bluetooth_icon.xbm"


/* sine table, per degree, factor 100 */
int16_t sintab[]={
	    0,   2,   3,   5,   7,   9,  10,  12,  14,  16,
	   17,  19,  21,  22,  24,  26,  28,  29,  31,  33,
	   34,  36,  37,  39,  41,  42,  44,  45,  47,  48,
	   50,  52,  53,  54,  56,  57,  59,  60,  62,  63,
	   64,  66,  67,  68,  69,  71,  72,  73,  74,  75,
	   77,  78,  79,  80,  81,  82,  83,  84,  85,  86,
	   87,  87,  88,  89,  90,  91,  91,  92,  93,  93,
	   94,  95,  95,  96,  96,  97,  97,  97,  98,  98,
	   98,  99,  99,  99,  99, 100, 100, 100, 100, 100,
	  100, 100, 100, 100, 100, 100,  99,  99,  99,  99,
	   98,  98,  98,  97,  97,  97,  96,  96,  95,  95,
	   94,  93,  93,  92,  91,  91,  90,  89,  88,  87,
	   87,  86,  85,  84,  83,  82,  81,  80,  79,  78,
	   77,  75,  74,  73,  72,  71,  69,  68,  67,  66,
	   64,  63,  62,  60,  59,  57,  56,  54,  53,  52,
	   50,  48,  47,  45,  44,  42,  41,  39,  37,  36,
	   34,  33,  31,  29,  28,  26,  24,  22,  21,  19,
	   17,  16,  14,  12,  10,   9,   7,   5,   3,   2,
	    0,  -2,  -3,  -5,  -7,  -9, -10, -12, -14, -16,
	  -17, -19, -21, -22, -24, -26, -28, -29, -31, -33,
	  -34, -36, -37, -39, -41, -42, -44, -45, -47, -48,
	  -50, -52, -53, -54, -56, -57, -59, -60, -62, -63,
	  -64, -66, -67, -68, -69, -71, -72, -73, -74, -75,
	  -77, -78, -79, -80, -81, -82, -83, -84, -85, -86,
	  -87, -87, -88, -89, -90, -91, -91, -92, -93, -93,
	  -94, -95, -95, -96, -96, -97, -97, -97, -98, -98,
	  -98, -99, -99, -99, -99,-100,-100,-100,-100,-100,
	 -100,-100,-100,-100,-100,-100, -99, -99, -99, -99,
	  -98, -98, -98, -97, -97, -97, -96, -96, -95, -95,
	  -94, -93, -93, -92, -91, -91, -90, -89, -88, -87,
	  -87, -86, -85, -84, -83, -82, -81, -80, -79, -78,
	  -77, -75, -74, -73, -72, -71, -69, -68, -67, -66,
	  -64, -63, -62, -60, -59, -57, -56, -54, -53, -52,
	  -50, -48, -47, -45, -44, -42, -41, -39, -37, -36,
	  -34, -33, -31, -29, -28, -26, -24, -22, -21, -19,
	  -17, -16, -14, -12, -10,  -9,  -7,  -5,  -3,  -2
};

int16_t f_sin(int16_t v)
{
	v %= 360;
	return sintab[v];
}

int16_t f_cos(int16_t v)
{
	v += 90;
	v %= 360;
	return sintab[v];
}

void DrawLcdAnaClock(boolean show_seconds)
{
	int16_t i, x, y, x2, y2;
	int16_t tmp;
	int8_t hour, minute, seconds;
	char tstr[16];

	hour = OswaldClk.hour;
	minute = OswaldClk.minute;
	seconds = OswaldClk.second;

	hour -= 3;
	if (hour < 0)
		hour += 12;
	// mf = (1. / 59.) * (double)minute;
	minute -= 15;
	if (minute < 0)
		minute += 60;
	seconds -= 15;
	if (seconds < 0)
		seconds += 60;

	hal_lcd_clear_display();

	SetFont(MetaWatch16);
	snprintf(tstr, 16, "%02d", OswaldClk.day);
	WriteLcdString(70, 40, tstr);

	// plot(R*cos(360° * i/N), R*sin(360° * i/N))
	for (i=0; i<12; i++) {
		tmp = 48 + ((43 * f_cos((360 / 12) * i)) / 100);
		x =  tmp;
		tmp = 48 + ((43 * f_sin((360 / 12) * i)) / 100);
		y =  tmp;
		tmp = 48 + ((48 * f_cos((360 / 12) * i)) / 100);
		x2 =  tmp;
		tmp = 48 + ((48 * f_sin((360 / 12) * i)) / 100);
		y2 =  tmp;
		DrawLcdLineBresenhamWW(x, y, x2, y2, 2);
	};

	// Hour
	tmp = 48 + (30 * f_cos(((360 / 12) * hour) + ((OswaldClk.minute * 360) /12 / 60)) / 100);
	x =  tmp;
	tmp = 48 + (30 * f_sin(((360 / 12) * hour) + ((OswaldClk.minute * 360) /12 / 60)) / 100);
	y =  tmp;
	DrawLcdLineBresenhamWW(48, 48, x, y, 2);
	// Minute
	tmp = 48 + ((40 * f_cos((360 / 60) * minute)) / 100);
	x =  tmp;
	tmp = 48 + ((40 * f_sin((360 / 60) * minute)) / 100);
	y =  tmp;
	DrawLcdLineBresenhamWW(48, 48, x, y, 2);
	if (show_seconds) {
		// Seconds
		tmp = 48 + ((40 * f_cos((360 / 60) * seconds)) / 100);
		x =  tmp;
		tmp = 48 + ((40 * f_sin((360 / 60) * seconds)) / 100);
		y =  tmp;
		DrawLcdLineBresenham(48, 48, x, y);
	};

	hal_lcd_update_display();
}

void DrawLcdDigitalClock(boolean show_seconds)
{
	int gRow = 3;
	int gColumn = 3;
	char tstr[16];
	int i;

	SetFont(MetaWatchTime);

	hal_lcd_clear_display();
	//gRow += WriteLcdCharacter(ui, gRow, gColumn, TIME_CHARACTER_SPACE_INDEX);
	if (OswaldClk.clk24hr) {
		gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.hour / 10));
		gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.hour % 10));
	} else {
		unsigned char val = OswaldClk.hour;
		if (val > 12)
			val -= 12;
		gRow += WriteLcdCharacter(gRow, gColumn, (val / 10));
		gRow += WriteLcdCharacter(gRow, gColumn, (val % 10));
	}
	gRow += WriteLcdCharacter(gRow, gColumn, TIME_CHARACTER_COLON_INDEX);
	gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.minute / 10));
	gRow += WriteLcdCharacter(gRow, gColumn, (OswaldClk.minute % 10));

	gRow += 3;
	if (show_seconds) {
		SetFont(MetaWatch16);
		snprintf(tstr, 16, "%02d", OswaldClk.second);
		WriteLcdString(gRow, 9, tstr);
	};

	SetFont(MetaWatch7);

	if (!OswaldClk.clk24hr) {
		if (OswaldClk.hour > 12) {
			WriteLcdString(gRow, 3, "PM");
		} else {
			WriteLcdString(gRow, 3, "AM");
		}
	}

	SetFont(MetaWatch16);

	if (OswaldClk.day_first)
		snprintf(tstr, 16, "%d.%d.%d", OswaldClk.day, OswaldClk.month, OswaldClk.year);
	else
		snprintf(tstr, 16, "%d/%d %d", OswaldClk.month, OswaldClk.day, OswaldClk.year);
	WriteLcdString(3, 25, tstr);

	if (OswaldPowerState.source)
		oswald_draw_bitmap(81, 4, charger_icon_width, charger_icon_height, charger_icon_bits);

	if (OswaldPowerState.percent > 75)
		oswald_draw_bitmap(81, 4, battery100_icon_width, battery100_icon_height, battery100_icon_bits);
	else if (OswaldPowerState.percent > 50)
		oswald_draw_bitmap(81, 4, battery75_icon_width, battery75_icon_height, battery75_icon_bits);
	else if (OswaldPowerState.percent > 25)
		oswald_draw_bitmap(81, 4, battery50_icon_width, battery50_icon_height, battery50_icon_bits);
	else if (OswaldPowerState.percent > 5)
		oswald_draw_bitmap(81, 4, battery25_icon_width, battery25_icon_height, battery25_icon_bits);
	else
		oswald_draw_bitmap(81, 4, battery0_icon_width, battery0_icon_height, battery0_icon_bits);


	if (hal_bluetooth_get_state() >= BLUETOOTH_ON)
		oswald_draw_bitmap(81, 4, bluetooth_icon_width, bluetooth_icon_height, bluetooth_icon_bits);

	gRow = 0;
	gColumn = 45;
	SetFont(MetaWatch5);
	for (i=0; i<strlen(MainMessage); i++) {
		gRow += WriteLcdCharacter(gRow, gColumn, MainMessage[i]);
		if (gRow > 90) {
			gRow = 0;
			gColumn += 7;
		}
		if (gColumn > 95)
			i = 255;
	}
#if 0
	snprintf(tstr, 16, "%d%% (%dmV)", OswaldPowerState.percent, OswaldPowerState.level);
	WriteLcdString(2, 48, tstr);
	WriteLcdString(2, 64, OswaldPowerState.source ? "ext" : "bat");

	/* this makes only sense when the charger is active */
	if (OswaldPowerState.source) {
		switch (OswaldPowerState.charge_state) {
			case POWER_CHARGER_DONE:
				WriteLcdString(2, 80, "charge done");
				break;
			case POWER_CHARGER_PRECHARGE:
				WriteLcdString(2, 80, "precharging");
				break;
			case POWER_CHARGER_CHARGING:
				WriteLcdString(2, 80, "charging");
				break;
			case POWER_CHARGER_UNK:
				WriteLcdString(2, 80, "charge unkn.");
				break;
			default:
				break;
		};
	};
#endif
	hal_lcd_update_display();
}