#include <fxcg/display.h>
#include <fxcg/keyboard.h>
#include <fxcg/system.h>
#include <fxcg/misc.h>
#include "sprites.h"
void CopySpriteMasked(const color_t* data, int x, int y, int width, int height) {
  color_t* VRAM = (color_t*)0xA8000000; 
  VRAM += (LCD_WIDTH_PX*y + x); 
  while(height--) {
    int i=width;
    while(i--){
      if(*data!=BGC) {
        *(VRAM++) = *(data++);
      } else {
        ++VRAM;
        ++data;
      }
    }
    VRAM += (LCD_WIDTH_PX-width);
  }
}
void ColorArea(color_t color, int x, int y, int width, int height) {
	color_t* VRAM = (color_t*)0xA8000000; 
	VRAM += (LCD_WIDTH_PX*y + x); 
	while(height--) {
		int i=width;
		while(i--){
			*(VRAM++) = color;
		}
		VRAM += (LCD_WIDTH_PX-width);
	}
}
void SwitchSpriteMasked(const color_t* data, int x, int y, int width, int height, int On) {
	color_t* VRAM = (color_t*)0xA8000000; 
	VRAM += (LCD_WIDTH_PX*y + x); 
	int i;
	if (On) {
		while(height--) {
		i=width;
		while(i--){
			if(*data!=BGC) {
				*(VRAM++) = *(data++);
			} else {
				++VRAM;
				++data;
			}
		}
		VRAM += (LCD_WIDTH_PX-width);
	  }
	}else{
		while(height--) {
		i=width;
		while(i--){
			if(*data!=BGC) {
				*(VRAM++) = BGC;
			} else {
				++VRAM;
				++data;
			}
		}
		VRAM += (LCD_WIDTH_PX-width);
	  }
	}
}
// Thanks to AHelper and http://prizm.cemetech.net/index.php?title=RTC_Unit for these
#define RSECCNT (unsigned char*)0xA413FEC2
#define RMINCNT (unsigned char*)0xA413FEC4
#define RHRCNT  (unsigned char*)0xA413FEC6
#define RWKCNT  (unsigned char*)0xA413FEC8
#define RDAYCNT (unsigned char*)0xA413FECA
#define RMONCNT (unsigned char*)0xA413FECC
// #define RYRCNT (unsigned short*)0xA413FECE
// #define RCR2    (unsigned char*)0xA413FEDE
void SwitchBarMasked(int n, int x, int y, int width, int height, int On) {
	color_t* VRAM = (color_t*)0xA8000000; 
	VRAM += (LCD_WIDTH_PX*y + x); 
	int i;
	int j=0;
	if (On) {
		while(height--) {
		i=width;
		while(i--){
			color_t p = Bars[n][j];
			if(p!=BGC) {
				*(VRAM++) = p;
			} else {
				++VRAM;
			}
			++j;
		}
		VRAM += (LCD_WIDTH_PX-width);
	  }
	}else{
		while(height--) {
		i=width;
		while(i--){
			color_t p = Bars[n][j];
			if(p!=BGC) {
				*(VRAM++) = BGC;
			} else {
				++VRAM;
			}
			++j;
		}
		VRAM += (LCD_WIDTH_PX-width);
	  }
	}
}
void SwitchCapMasked(int n, int x, int y, int width, int height, int On) {
	color_t* VRAM = (color_t*)0xA8000000; 
	VRAM += (LCD_WIDTH_PX*y + x); 
	int i;
	int j=0;
	if (On) {
		while(height--) {
		i=width;
		while(i--){
			color_t p = Barc[n][j];
			if(p!=BGC) {
				*(VRAM++) = p;
			} else {
				++VRAM;
			}
			++j;
		}
		VRAM += (LCD_WIDTH_PX-width);
	  }
	}else{
		while(height--) {
		i=width;
		while(i--){
			color_t p = Barc[n][j];
			if(p!=BGC) {
				*(VRAM++) = BGC;
			} else {
				++VRAM;
			}
			++j;
		}
		VRAM += (LCD_WIDTH_PX-width);
	  }
	}
}
void SwitchDatMasked(int n, int x, int y, int width, int height, int On) {
	color_t* VRAM = (color_t*)0xA8000000; 
	VRAM += (LCD_WIDTH_PX*y + x); 
	int i;
	int j=0;
	if (On) {
		while(height--) {
		i=width;
		while(i--){
			color_t p = Bard[n][j];
			if(p!=BGC) {
				*(VRAM++) = p;
			} else {
				++VRAM;
			}
			++j;
		}
		VRAM += (LCD_WIDTH_PX-width);
	  }
	}else{
		while(height--) {
		i=width;
		while(i--){
			color_t p = Bard[n][j];
			if(p!=BGC) {
				*(VRAM++) = BGC;
			} else {
				++VRAM;
			}
			++j;
		}
		VRAM += (LCD_WIDTH_PX-width);
	  }
	}
}
void SwitchDayMasked(int n, int x, int y, int width, int height, int On) {
	color_t* VRAM = (color_t*)0xA8000000; 
	VRAM += (LCD_WIDTH_PX*y + x); 
	int i;
	int j=0;
	if (On) {
		while(height--) {
		i=width;
		while(i--){
			color_t p = Barw[n][j];
			if(p!=BGC) {
				*(VRAM++) = p;
			} else {
				++VRAM;
			}
			++j;
		}
		VRAM += (LCD_WIDTH_PX-width);
	  }
	}else{
		while(height--) {
		i=width;
		while(i--){
			color_t p = Barw[n][j];
			if(p!=BGC) {
				*(VRAM++) = BGC;
			} else {
				++VRAM;
			}
			++j;
		}
		VRAM += (LCD_WIDTH_PX-width);
	  }
	}
}
#define LCDC *(unsigned short*)(0xB4000000)//Thanks to TeamFX https://www.cemetech.net/forum/viewtopic.php?t=11908
int GetBacklightSubLevel_RAW(){// by gbl08ma https://github.com/gbl08ma/utilities
  Bdisp_DDRegisterSelect(0x5a1);
  return (LCDC & 0xff) - 6;
}
#define VRAM0 ((color_t *)0xA8000000)
int main() {
	unsigned short key = 0;
	int keyCol; int keyRow;
    Bdisp_EnableColor(1);
    Bdisp_AllClr_VRAM();
	locate_OS(1,1);
	Bdisp_Fill_VRAM(BGC, 3);
	DrawFrame(BGC);
	int ss, ss1, ss2;
	int  PM, PM0 = 0;
	int nn1, nn2;
	int hh, h1, h2;
	int d1, d2;
	int m1, m2;
	int ss0  = -1;
	int ss10 = 10;
	int ss20 = 10;
	int nn10 = 10;
	int nn20 = 10;
	int h10 = 10;
	int h20 = 10;
	int d10 = 10;
	int d20 = 10;
	int m10 = 10;
	int m20 = 10;
	int ww, w1, w2;	
	int ww0 = -1;
	int w10 = 7;
	int w20 = 7;
	int fill;
	CopySpriteMasked(_tl,166,14,8,8);
	ColorArea(0xad75,174,14,186,1);
	ColorArea(0,174,15,186,4);
	ColorArea(0xdedb,174,19,186,1);
	CopySpriteMasked(_tr,360,14,8,8);
	ColorArea(0xdedb,166,22,1,70);
	ColorArea(0,167,22,4,70);
	ColorArea(0xad75,171,22,1,70);
	ColorArea(0,256,52,17,7);//hyphen
	ColorArea(0,363,22,5,70);
	CopySpriteMasked(_bl,166,92,8,8);
	ColorArea(0xdedb,174,94,186,1);
	ColorArea(0,174,95,186,4);
	ColorArea(0xad75,174,99,186,1);
	CopySpriteMasked(_br,360,92,8,8);
	int initial = GetBacklightSubLevel_RAW();
	int backlight = initial; 
	int backlight0 = 0;
	CopySpriteMasked(_dot,133,142,14,16);
	CopySpriteMasked(_dot,131,181,14,16);
	while(1){
		if (*(VRAM0+0x2100) == 0x0000) main();
		backlight = GetBacklightSubLevel_RAW();
		if (initial != backlight && backlight0 != backlight) {
			SwitchSpriteMasked(_light,305,110,48,33,0);
			backlight0 = backlight;
		}else if (backlight0 != backlight) {
			SwitchSpriteMasked(_light,305,110,48,33,1);
			backlight0 = backlight;
		}
		ss1 = ((*(RSECCNT))&0xf0)>>4;
		ss2 = (*(RSECCNT))&0x0f;
		ss = ss1*10 + ss2;
		if (ss0 != ss) {
			ss0 = ss;
			if (ss10 != ss1) {
				for (int n = 0; n<7; n++) {
					fill = OnOff[ss1][n];
					if (fill != OnOff[ss10][n]) SwitchBarMasked(n, ss_x[0]+ssbar_x[n], ss_y+ssbar_y[n], ssbar_w[n], ssbar_h[n], fill);
				}
				ss10 = ss1;
			}
			if (ss20 != ss2) {
				for (int n = 0; n<7; n++) {
					fill = OnOff[ss2][n];
					if (fill != OnOff[ss20][n]) SwitchBarMasked(n, ss_x[1]+ssbar_x[n], ss_y+ssbar_y[n], ssbar_w[n], ssbar_h[n], fill);
				}
				ss20 = ss2;
			}
			nn1 = ((*(RMINCNT))&0xf0)>>4;
			nn2 = (*(RMINCNT))&0x0f;
			if (nn10 != nn1) {
				for (int n = 0; n<7; n++) {
					fill = OnOff[nn1][n];
					if (fill != OnOff[nn10][n]) SwitchCapMasked(n, cap_x[2]+capbar_x[n], cap_y+capbar_y[n], capbar_w[n], capbar_h[n], fill);
				}
				nn10 = nn1;
			}
			if (nn20 != nn2) {
				for (int n = 0; n<7; n++) {
					fill = OnOff[nn2][n];
					if (fill != OnOff[nn20][n]) SwitchCapMasked(n, cap_x[3]+capbar_x[n], cap_y+capbar_y[n], capbar_w[n], capbar_h[n], fill);
				}
				nn20 = nn2;
			}
			h1 = ((*(RHRCNT))&0xf0)>>4;
			h2 = (*(RHRCNT))&0x0f;
			hh = h1*10 + h2;
			if(hh > 11) { 
				if (hh > 12) hh -= 12;
				PM = 1;
			}else PM = 0;
			if (PM0 != PM) {
				PM0 = PM;
				SwitchSpriteMasked(_PM,17,94,38,21,PM);
			}
			if (hh < 10) h1 = 10; else h1 = 1;
			if (h10 != h1) {
				for (int n = 0; n<7; n++) {
					fill = OnOff[h1][n];
					if (fill != OnOff[h10][n]) SwitchCapMasked(n, cap_x[0]+capbar_x[n], cap_y+capbar_y[n], capbar_w[n], capbar_h[n], fill);
				}
				h10 = h1;
			}
			h2 = hh % 10;
			if (h20 != h2) {
				for (int n = 0; n<7; n++) {
					fill = OnOff[h2][n];
					if (fill != OnOff[h20][n]) SwitchCapMasked(n, cap_x[1]+capbar_x[n], cap_y+capbar_y[n], capbar_w[n], capbar_h[n], fill);
				}
				h20 = h2;
			}
			d1 = ((*(RDAYCNT))&0xf0)>>4;
			d2 = (*(RDAYCNT))&0x0f;
			ww = (*RWKCNT & 0b111);
			if (ww0 != ww) {
				ww0 = ww;
				w1 = WD[0][ww];//ww;
				if (w10 != w1) {
					for (int n = 0; n<8; n++) {
						fill = WDays[0][w1][n];
						if (fill != WDays[0][w10][n]) SwitchDayMasked(n+1, day_x[0]+daybar_x[n+1], day_y+daybar_y[n+1], daybar_w[n+1], daybar_h[n+1], fill);
					}
					w10 = w1;
				}
				w2 = WD[1][ww];//ww;
				if (w20 != w2) {
					for (int n = 0; n<8; n++) {
						fill = WDays[1][w2][n];
						if (fill != WDays[1][w20][n]) SwitchDayMasked(n, day_x[1]+daybar_x[n], day_y+daybar_y[n], daybar_w[n], daybar_h[n], fill);
					}
					w20 = w2;
				}
			}
			if (d1 == 0) d1 = 10;
			if (d10 != d1) {
				for (int n = 0; n<7; n++) {
					fill = OnOff[d1][n];
					if (fill != OnOff[d10][n]) SwitchDatMasked(n, dat_x[2]+datbar_x[n], dat_y+datbar_y[n], datbar_w[n], datbar_h[n], fill);
				}
				d10 = d1;
			}
			if (d20 != d2) {
				for (int n = 0; n<7; n++) {
					fill = OnOff[d2][n];
					if (fill != OnOff[d20][n]) SwitchDatMasked(n, dat_x[3]+datbar_x[n], dat_y+datbar_y[n], datbar_w[n], datbar_h[n], fill);
				}
				d20 = d2;
			}
			m1 = ((*(RMONCNT))&0xf0)>>4;
			m2 = (*(RMONCNT))&0x0f;
			if (m1 == 0) m1 = 10;
			if (m10 != m1) {
				for (int n = 0; n<7; n++) {
					fill = OnOff[m1][n];
					if (fill != OnOff[m10][n]) SwitchDatMasked(n, dat_x[0]+datbar_x[n], dat_y+datbar_y[n], datbar_w[n], datbar_h[n], fill);
				}
				m10 = m1;
			}
			if (m20 != m2) {
				for (int n = 0; n<7; n++) {
					fill = OnOff[m2][n];
					if (fill != OnOff[m20][n]) SwitchDatMasked(n, dat_x[1]+datbar_x[n], dat_y+datbar_y[n], datbar_w[n], datbar_h[n], fill);
				}
				m20 = m2;
			}
			Bdisp_PutDisp_DD();
        }
		GetKeyWait_OS(&keyCol, &keyRow, 2, 0, 0, &key);//just to handle the Menu key//by gbl08ma https://github.com/gbl08ma/utilities
	}
}