#if defined(WIN32)
#include <curses.h>
#else
#include <ncurses.h> //getch printw addch attron attroff
#endif
#include <unistd.h> //sleep unix only
#include <time.h>  //clock
#include "cornolio.h"

void TBegin(){
	initscr();
	cbreak();
	noecho();
	nodelay(stdscr,1);
	keypad(stdscr,1);
	mousemask(ALL_MOUSE_EVENTS, NULL);
	if (has_colors() == 0 ){
		printw("no color");
	}
	else{
		start_color();
		use_default_colors();
		int colorstbl[] = {
			COLOR_BLACK,COLOR_RED,COLOR_GREEN,COLOR_BLUE,
			COLOR_WHITE,COLOR_CYAN,COLOR_YELLOW,COLOR_MAGENTA
		};
		for(Color c=Black; c<Colors; c++){
			init_pair(c+2,colorstbl[c%8],colorstbl[c/8]);
		}
		init_pair(Black+2,COLOR_BLACK,COLOR_BLACK);
	}
}


void TEnd(){
	endwin();
}

void Prnt(Let txt[], Let col, Let row, Color clr){
	attrset(0);
	if (clr > Colors) attron(A_BOLD);
	attron(COLOR_PAIR((clr%Colors)+2));
	move(row,col);
	printw(txt);
}

void Lbl(Let txt[], Let col, Let row, Color clr){
	attrset(0);
	if (clr > Colors) attron(A_BOLD);
	attron(COLOR_PAIR((clr%Colors)+2));
	for(char*c=txt;*c!=0;c++){
		move(row++,col);
		addch(*c);
	}
}

void Plt(Let col, Let row, Color clr){
	attrset(0);
	if (clr > Colors ) attron(A_BOLD);
	attron(COLOR_PAIR((clr%Colors)+2));
	move(row,col);
	addch(ACS_CKBOARD);
}

void Sym(Symbol s,Let col, Let row,Color clr){
	attrset(0);
	if (clr > Colors) attron(A_BOLD);
	attron(COLOR_PAIR((clr%Colors)+2));
	move(row,col);
	switch(s){
	case North:
	case South:
	case Vline:	addch(ACS_VLINE);	break;
	case East:
	case West:
	case Hline:	addch(ACS_HLINE);	break;
	case Rose:	addch(ACS_PLUS); 	break;
	case Lne:	addch(ACS_LLCORNER);	break;
	case Lse:	addch(ACS_ULCORNER);	break;
	case Lsw:	addch(ACS_URCORNER);	break;
	case Lnw:	addch(ACS_LRCORNER);	break;
	case Tnn:	addch(ACS_TTEE);	break;
	case Tne:	addch(ACS_RTEE);	break;
	case Tns:	addch(ACS_BTEE);	break;
	case Tnw:	addch(ACS_LTEE);	break;
	case Here:	addch(ACS_BULLET);	break;
    case Larr: addch(ACS_LARROW);     break;
    case Rarr: addch(ACS_RARROW);     break;
    case Uarr: addch(ACS_UARROW);     break;
    case Darr: addch(ACS_DARROW);     break;
    case Top: addch(ACS_S1);    break;
    case Bottom: addch(ACS_S9); break;
    case Diamond: addch(ACS_DIAMOND); break;
	default:	addch(s);
	}	
}



/*
rethinking
this part will not be limited to nes like control
lets appropriate all laptop key
	current Btn/Clr combo may be refactored to take a key list
lets appropriate mouse capability
	with possible keyboard cursor
lets make text input
	with position because it will draw on screen as you type
on screen keyboard XD
	enable android XD
	good use case for devlopment
	14 buttons wide top row
   [esc]
   [~][1][2][3][4][5][6][7][8][9][0][-][=][<-]
  [tab][q][w][e][r][t][y][u][i][o][p][{][}][\]
        [a][s][d][f][g][h][j][k][l][;]['][<-/]
  [shift][z][x][c][v][b][n][m][,][.][/][shift]
  [ctrl][alt][     space bar      ][alt][ctrl]

ESC is 27 followed by -1
ALT is 27 followed by the combination key
typedef enum BUTT {
	Down=KEY_DOWN,	//the four arrow keys
	Up=KEY_UP,
	Left=KEY_LEFT,
	Right=KEY_RIGHT,
	Home=KEY_HOME,	//home key (upward+left arrow)
	Back=KEY_BACKSPACE,	//backspace
	Enter=KEY_ENTER	//enter or send
} Butt;
// from a list of key pressed or not
// set them all as unpressed
// scan keyboad and replace all key that match 
// with its pressed counterpart
void Keyb(Key []);
// from a list of key pressed or not
// check if the desired key is pressed
Let Pressed(Key [], Key);
// fetch mouse / keyboard version too
Let CursorCol();
Let CursorRow();
Let CursorBtn();
// just input text 
void Input(Let []);
*/



clock_t LastTck = 0;
void Tck(){

}

int mx;
int my;

Key key[Keys];
#define Press(k) key[(k)] = 1
#define IsPressed(k) key[(k)]
void Clr(){
	//refresh screen
	refresh();
	//let user time to notice it
	clock_t RangeTck = CLOCKS_PER_SEC / Fps;
	unsigned int USleepMax = 1000000 / Fps;
	unsigned int slp = USleepMax;
	clock_t nowTck = clock();
	clock_t diffTck = nowTck - LastTck;
	if (diffTck < RangeTck){
		clock_t TimeLeft = RangeTck - diffTck;
		slp = USleepMax * TimeLeft / RangeTck;
	}	
	usleep(slp);
	//gather all input since
	for(int i=Any;i<Keys;i++){
		key[i] = 0;
	}
	int k = getch();
	MEVENT mouse;
	while (k != ERR){
         key[Any] = 1;
         switch(k){
            case KEY_MOUSE:
                if (getmouse(&mouse) == OK){
            		Press(Click);
                    mx = mouse.x;
                    my = mouse.y;
	            }
		        break;
            case 27 : 
                if (getch() == ERR)
                Press(Esc);
                break;
            case 'Q': key[Kshift] = 1;
            case 'q': 
                Press(Kq);
                Press(Esc);
                break;
            case 'W': Press(Kshift);
            case 'w': Press(Kw);
            case KEY_UP: Press(Up); 
                break;
            case 'E': key[Kshift] = 1;
            case 'e': key[Ke] = 1; 
                break;
            case 'R': key[Kshift] = 1;
            case 'r': key[Kr] = 1;
                break;
            case 'T': key[Kshift] = 1;
            case 't': key[Kt] = 1;
                break;
            case 'Y': key[Kshift] = 1;
            case 'y': key[Ky] = 1;
                break;
            case 'U': key[Kshift] = 1;
            case 'u': key[Ku] = 1;
                break;
            case 'I': key[Kshift] = 1;
            case 'i': key[Ki] = 1;
                break;
            case 'O': key[Kshift] = 1;
            case 'o': key[Ko] = 1;
                break;
            case 'P': key[Kshift] = 1;
            case 'p': key[Kp] = 1;
                break;

            case 'A': key[Kshift] = 1;
			case 'a': key[Ka] = 1;
			case KEY_LEFT: 	key[Lt] = 1; 
				break;
            case 'S': key[Kshift] = 1;
			case 's': key[Ks] = 1;
			case KEY_DOWN: 	key[Dn] = 1; 
				break;
            case 'D': key[Kshift] = 1;
			case 'd': key[Kd] = 1;
			case KEY_RIGHT:	key[Rt] = 1; 
				break;

            case 'F': key[Kshift] = 1;
            case 'f': key[Kf] = 1;
                break;
            case 'G': key[Kshift] = 1;
            case 'g': key[Kg] = 1;
                break;
            case 'H': key[Kshift] = 1;
            case 'h': key[Kh] = 1;
                break;
            case 'J': key[Kshift] = 1;
            case 'j': key[Kj] = 1;
                break;
            case 'K': key[Kshift] = 1;
            case 'k': key[Kk] = 1;
                break;
            case 'L': key[Kshift] = 1;
            case 'l': key[Kl] = 1;
                break;

            case 'Z': key[Kshift] = 1;
			case 'z': key[Kz] = 1;
			case KEY_BACKSPACE: key[Back] = 1; 
				break;
            case 'X': key[Kshift] = 1;
			case 'x': key[Kx] = 1;
			case KEY_ENTER:	key[Enter] = 1; 
				break;
            case 'C': key[Kshift] = 1;
			case 'c': key[Kc] = 1;
			case ' ': key[Space] = 1; 
				break;

            case 'V': key[Kshift] = 1;
            case 'v': key[Kv] = 1;
                break;
            case 'B': key[Kshift] = 1;
            case 'b': key[Kb] = 1;
                break;
            case 'N': key[Kshift] = 1;
            case 'n': key[Kn] = 1;
                break;
            case 'M': key[Kshift] = 1;
            case 'm': key[Km] = 1;
                break;

            case '1': key[K1] = 1;
                break;
            case '2': key[K2] = 1;
                break;
            case '3': key[K3] = 1;
                break;
            case '4': key[K4] = 1;
                break;
            case '5': key[K5] = 1;
                break;
            case '6': key[K6] = 1;
                break;
            case '7': key[K7] = 1;
                break;
            case '8': key[K8] = 1;
                break;
            case '9': key[K9] = 1;
                break;
            case '0': key[K0] = 1;
                break;
		}
		k = getch();
	}
}

int Btn(Key btn){
	return key[btn];
}
int Mx(){
	return mx;
}
int My(){
	return my;
}
