#include "texted.h"
#define MAX_SIZE 1048576

/* ********************************************************************************************************************************************** */

//	STUFF TO IMPLEMENT

//	******DONE****** 1. Characters should be removed from array after backspace (maybe keep track of which element in the array the cursor is on.
//	******DONE****** 2. Enter should add newline character to array.
//	******DONE****** 3. Backspace and Left Arrow at first character in row should move up to the last character on the previous row. (vice versa for right arrow)
//	********(PAGE UP AND) PAGE DOWN SOMETIMES DOESN'T MOVE REAL CURSOR ACCORDINGLY - TEXTCOUNTER SHOULD BE ADJUSTED******** 4. Page scrolling up/down (initially with page up/page down keys). - Idea: Implement by printing from nth new line character till first null character.
//	5. (OPTIONAL): Convert the mainwin into a pad, to make scrolling easier.
//	**KIND OF DONE** 6. Word wrapping.
//	******DONE****** 7. Getting Save File Location from argv
//	******DONE?***** 8. Up Arrow and Down Arrow Keys.
//	******DONE****** 9. Integrate with file manager program.
//	******DONE****** 10. Opening and editing text files
//	**MOSTLY DONE*** 11. Save Dialog.
//	******DONE****** 12. Insert character into array after pressing left arrow and typing a character.

//	SOLVE ERROR WITH LAST LINE IN A FILE (IT DOESN'T HAVE MAINX CHARACTERS AND IT DOESN'T HAVE TWO NEWLINES)

//	******DONE****** 13. Backspace at first character ignores spaces.
//	******DONE?***** 14. Adding character at last line of window.
//	******DONE?***** 15. Page down/Page up with word wrapping.


/* ********************************************************************************************************************************************** */




int run(char* dir) {
	char* text;
	char* saveLocation;
//	char* tempSaveLoc;
	int textCounter;
	int selRow=1;
//	int numCharsCurrent;
//	int numCharsNext;
	int selCol=1;
	int xSize,ySize,mainX,mainY;
	int charArrayCounter;
	FILE* myFile;
	int ch;
	int numLines;
	bool newLineFound;
//	int textIndex;
//	char* shortText;
	int upArrowDistance;
	int charsOnLine;


	text = malloc(MAX_SIZE * (sizeof(char)));

	initscr();
	noecho();
//	cbreak();
	raw();
	getmaxyx(stdscr,ySize,xSize);

//	mvwaddstr(stdscr,2,5,"^S - Save | ^C - Quit | ^R - Reset Cursor");  


	mvwaddstr(stdscr,2,5,"^S - Save | ^C - Quit | <Page Down> - Scroll Down | <Page Up> - Scroll Up");  



//	WINDOW* boxwin = newwin(ySize-7,xSize-8,5,5);
	WINDOW* mainwin = newwin(ySize-7,xSize-9,5,5);
	keypad(mainwin,true);
//	box(boxwin,0,0);
	getmaxyx(mainwin,mainY,mainX);
	refresh();
	wrefresh(mainwin);
//	wrefresh(boxwin);
	wmove(mainwin,selRow,selCol);
//	ch = wgetch(mainwin);
	ch = ' ';
	textCounter=0;
	numLines=0;
	int numNewLinesFound=0;
	int indexToBegin=0;
	FILE* readFile;
//	int tempSelRow,tempSelCol;

//	if (argc > 1) {
		if (readFile = fopen(dir,"r")) {
			fread(text,MAX_SIZE,1,readFile);
			printFromIndex(mainwin,text,0,1,1,0);		
//		} else {
//			strcpy(argv[1],tempSaveLoc);
		}
//	}
	wmove(mainwin,selRow,selCol);

	while (ch != ('s' & 0x1f) && (ch != ('c' & 0x1f))) {
		indexToBegin=0;
		numNewLinesFound=0;
		charsOnLine=0;
		if (numLines > 0) {
			for (int i=0;i<strlen(text);i++) {
				if (numNewLinesFound==numLines) {
					indexToBegin=i;
					break;
				}
				if (*(text+i)=='\n') {
					numNewLinesFound++;
					charsOnLine=0;
				} else {
					charsOnLine++;
				}

				if (charsOnLine>=mainX-2){
					numNewLinesFound++;
					charsOnLine=0;
				}
			}
		}	
  //   		if (indexToBegin!=0){
			printFromIndex(mainwin,text,indexToBegin,selRow,selCol,numLines);
  //		}
//		box(mainwin,0,0);



		//		getyx(mainwin,selRow,selCol);
		wmove(stdscr,1,1);
		wclrtoeol(stdscr);
		mvwprintw(stdscr,1,1,"%d,%d",selRow,selCol);

		mvwprintw(stdscr,3,1,"%c",findCharInArray(text,2,1,numLines));

		wmove(mainwin,selRow,selCol);

		ch = wgetch(mainwin);
		switch (ch) {
			case 7:
			case KEY_BACKSPACE:
			case 8:
			case 127:
				if (selCol > 1) {
					wmove(mainwin,selRow,--selCol);
					wdelch(mainwin);
					textCounter--;
					shiftElementsDown(text,textCounter);

				} else if (selCol == 1 && selRow > 1) {
					textCounter--;
					--selRow;
					selCol=findLastChar(mainwin,selRow,mainX)+charToNewLine(text,textCounter);
					wmove(mainwin,selRow,selCol);
					shiftElementsDown(text,textCounter);

				}
				break;

			case KEY_LEFT:
				if (selCol > 1) {
                                        wmove(mainwin,selRow,--selCol);
					textCounter--;
                                } else if (selCol == 1 && selRow > 1) {
                                        textCounter--;
                                        --selRow;
					selCol=findLastChar(mainwin,selRow,mainX)+charToNewLine(text,textCounter);
					if (selCol==2) {
						selCol--;
//						*(int*)0=0;
					}
                                        wmove(mainwin,selRow,selCol);
                                }

                                break;

			case KEY_RIGHT:
//				if (!(isLastChar(mainwin,selRow,selCol,mainX))) {


			if (*(text+textCounter) != '\0') {
				if (*(text+textCounter) != '\n' && selCol<mainX-2) {
						wmove(mainwin,selRow,++selCol);
					} else {
						selCol=1;
						wmove(mainwin,++selRow,selCol);
					}
					textCounter++;
	//				mvwprintw(mainwin,6,6,"%d",mvwinch(mainwin,selRow,selCol));
			}
					break;


			case KEY_HOME:
				textCounter-=selCol-1;
				selCol=1;
				wmove(mainwin,selRow,selCol);
				break;
			

			case KEY_DOWN:
				
				if (selCol == 1 && (*(text+textCounter+(findLastChar(mainwin,selRow,mainX)))) != '\0' && selRow<mainY-2) {


					while (*(text+textCounter) != '\n' &&  selCol<mainX-2){
						textCounter++;
						selCol++;
					}
					textCounter++;
					selCol=1;

				/*
					if (findLastChar(mainwin,selRow,mainX) > mainX-3) {
						textCounter--;
					}

                                        textCounter += (findLastChar(mainwin,selRow,mainX));


//					textCounter += (findLastCharWithArray(mainwin,stdscr,selRow,mainX,text,textCounter,numLines));	
//					selCol=1;
				*/

					wmove(mainwin,++selRow,selCol);
				}
				break;

                        case KEY_UP:

                                if (selRow-1 > 0 && (selCol == 1 && (*(text+textCounter-(findLastChar(mainwin,selRow-1,mainX)))) != '\0')) {
                                
					int selColOfNewLine = 500;
					newLineFound=false;
					upArrowDistance=0;
					for (int i=1;i<mainX;i++) {
//						if (*(text+textCounter+1) == '\n') {
//							newLineFound=true;
//						}

						if (i==mainX-1){
							upArrowDistance=mainX-1;
							break;
						}


						if (textCounter==i) {
							upArrowDistance=textCounter+1;
							break;
						}

						if (i == findLastChar(mainwin,selRow-1,mainX)) {
							upArrowDistance = findLastChar(mainwin,selRow-1,mainX);
							break;
						}


						if (*(text+textCounter-i) == '\n') {
							if (i<=2) {
								upArrowDistance=i;
								selColOfNewLine=i;
							} else {
								upArrowDistance=i-1;
							}
							if (newLineFound) {
								//if (findLastChar(mainwin,selRow-1,mainX) == 0) {
								//	upArrowDistance=2;
								//}

								break;
							}
							newLineFound=true;
						}
						 
					}
					


					textCounter-=upArrowDistance-1;

//					textCounter -= (findLastChar(mainwin,selRow-1,mainX));
//                                      selCol=1;
                                        wmove(mainwin,--selRow,selCol);
//					*(int*)0=0;
                           
				}
                                break;


			case 10:
//				wmove(mainwin,selRow+1,1);



				if (selRow < mainY-2) {
					wmove(mainwin,++selRow,1);
	
	
					shiftElementsUp(text,textCounter);
					*(text+textCounter) = '\n';
	
	
	
					textCounter++;
	//				selCol=1;
					selCol=1;
				}
				break;

			case KEY_DC:
//				abort();
				if (!(isLastChar(mainwin,selRow,selCol,mainX))) {
					wmove(mainwin,selRow,selCol+1);
					wdelch(mainwin);
//				textCounter--;
					shiftElementsDown(text,textCounter);
				}

				break;



//			case (('r' & 0x1f)):
//				wmove(mainwin,selRow,selCol);
//				break;


			case (('s' & 0x1f)):
//				abort();
//				shortText = shortenString(text);
//				if (argc > 1) {
					saveLocation = getSaveLoc(mainX,mainY,dir);	
//				} else {
//					saveLocation = getSaveLoc(mainX,mainY,"$$$");
//				}
				if (saveLocation == "$$$") {
					ch = ' ';
					wmove(mainwin,selRow,selCol);
					break;
				}
//				myFile = fopen("savedFile.txt","w");
				myFile = fopen(saveLocation,"w");
				mvwaddstr(stdscr,1,1,saveLocation);
				charArrayCounter=0;
				do {
					fputc(*(text+charArrayCounter),myFile);
					charArrayCounter++;
//				} while (charArrayCounter < (strlen(shortText)));
				} while (*(text+charArrayCounter) != '\0');

				if (*(text+charArrayCounter) != '\n') {
					fputc('\n',myFile);
				}
//				fputc('\0',myFile);
				fclose(myFile);
//				wgetch(mainwin);
				break;

			case KEY_NPAGE:
				if (selRow > 1) {
					numLines++;
					selRow--;
					wmove(mainwin,selRow,selCol);
				} else {
					if (selCol == 1) {
						numLines++;

						while (*(text+textCounter) != '\n' &&  selCol<mainX-2){
	     	                                	textCounter++;
                	                                selCol++;
						}
						textCounter++;
						selCol=1;


//						//textCounter += (findLastChar(mainwin,selRow,mainX));
						wmove(mainwin,selRow,selCol);
					}
				}
				break;

			case KEY_PPAGE:
					if (selRow >= mainY-2 && selCol == 1 && selRow > 1) {
	                                        textCounter -= (findLastChar(mainwin,selRow-1,mainX));
						selRow--;
					}
					if (numLines > 0){
						selCol=1;
						wmove(mainwin,selRow,selCol);
						numLines--;
						selRow++;
					}
	//				if (numLines == 0) {
	//					selRow++;
	//				}					
				break;
			default:
//				waddch(mainwin,ch);
				mvwinsch(mainwin,selRow,selCol,ch);
				if (*(text+textCounter+1-1) != '\0') {
					shiftElementsUp(text,textCounter);
				}
				*(text + textCounter) = ch;
				textCounter++;


	                if (selCol >= mainX-1) {
	                        selCol=2;
	                        selRow++;
        	                wmove(mainwin,selRow,selCol);
	                } else {


	//			selCol++;

//				/*Temporary uncomment*/
//				selCol++;
    //				wmove(mainwin,selRow,selCol+1);	

				wmove(mainwin,selRow,++selCol);

			}

//				mvwprintw(stdscr,1,2,"%d",*(text+textCounter-1));


//				mvwprintw(mainwin,6,6,"%d",ch);
			break;

		}
//		mvwprintw(mainwin,3,3,"%d",textCounter);
//		box(boxwin,0,0);
	}

	endwin();

	return 0;
}



char* shortenString (char* origString) {
	int numNullChars = 0;
	char* newString = malloc((strlen(origString)+1) * (sizeof(char)));
//	for (int i=0;i<strlen(newString)+1;i++) {
//		(*newString+i) = (*origString+i);
		strncpy(newString,origString,strlen(newString)+1);
//	}
	return newString;
}



void shiftElementsDown(char* arr,int arrCounter){

//	SHIFTS ELEMENTS LEFT

	int lastElement = strlen(arr)-1;
	for (int i=arrCounter+1;i<strlen(arr)+10;i++){
		*(arr+i-1) = *(arr+i);
	}
	*(arr+lastElement)='\0';


}


void shiftElementsUp(char* arr,int arrCounter) {

//	SHIFTS ELEMENTS RIGHT

	for (int i=strlen(arr)+2;i>=arrCounter;i--) {
		*(arr+i+1) = *(arr+i);
	}
	*(arr+arrCounter) = '\0';



}

char* getSaveLoc(int mainX,int mainY, char* tempSaveLoc) {
	WINDOW* saveDiag = newwin(8,40,((mainY/2)-4),((mainX/2)-20));
	char* saveLoc = malloc(SAVE_LOC_SIZE * sizeof(char));
	box(saveDiag,0,0);
	refresh();
	wrefresh(saveDiag);
	mvwaddstr(saveDiag,1,1,"Save to?");
	mvwhline(saveDiag,4,2,0,36);
	wmove(saveDiag,3,2);
	int i=0;
	char ch = 65;
	raw();
	int saveY,saveX;
//	cbreak();
	if (tempSaveLoc != "$$$") {
		do {
			wmove(saveDiag,3,i+2);

			waddch(saveDiag,*(tempSaveLoc+i));
			*(saveLoc+i) = *(tempSaveLoc+i);
			i++;
		} while (i<strlen(tempSaveLoc));
	}



	do {
		ch = wgetch(saveDiag);
		if (ch == 10) {
			break;
		}
		if (ch == ('c' & 0x1f)) {
			break;
		}
		getyx(saveDiag,saveY,saveX);
		if (ch == 127) {
			if (saveX > 2) {
				wmove(saveDiag,3,i+1);
//				wdelch(saveDiag);
				waddch(saveDiag,32);
				wmove(saveDiag,3,i+1);
				*(saveLoc+i-1) = '\0';		
				i--;
			}
		} else {
			wmove(saveDiag,3,i+2);
			waddch(saveDiag,ch);
			*(saveLoc+i) = ch;
			i++;
		}
		refresh();
		wrefresh(saveDiag);
	} while (ch != 10 && ch != ('c' & 0x1f));
//	raw();
	wclear(saveDiag);
	refresh();
	wrefresh(saveDiag);
//	return shortenString(saveLoc);
	if (ch == ('c' & 0x1f)) {
		return "$$$";
	}
	return saveLoc;



}


int findLastChar(WINDOW* mainwin,int selRow,int mainX) {
	int selCol=0;
	for (int i=mainX-1;i>=1;i--){
		if (mvwinch(mainwin,selRow,i) != 32) {
			selCol=i;
			break;
		}
	}

	if (selCol==0){
		return selCol;
	}

	return selCol+1;
}

int findLastCharWithArray(WINDOW* mainwin,WINDOW* std,int selRow,int mainX,char* text, int textCounter,int numLines) {
        int selCol=0;
        for (int i=0;i>mainX;i++){
//                if (findCharInArray(text,selRow,i+1,numLines) == mvwinch(mainwin,selRow+1,1)) {

		mvwprintw(stdscr,3,1,"%c\n",findCharInArray(text,selRow,i+1,numLines));

		if (findCharInArray(text,selRow,i+1,numLines) == '\n') {

			abort();
			selCol=i;
//			*(int*)0 = 0;
			break;
                }
        }
        return selCol+1;
}


bool isLastChar(WINDOW* mainwin,int selRow,int selCol,int mainX) {
	for (int i=selCol;i<mainX-1;i++) {
		if (mvwinch(mainwin,selRow,i) != 32) {
			return false;
		}
	}
	return true;
}


void printFromIndex(WINDOW* mainwin,char* text,int index,int selRow,int selCol,int numLines) {
	wclear(mainwin);
	refresh();
	wrefresh(mainwin);
	int mainY,mainX;
	getmaxyx(mainwin,mainY,mainX);

//	int index=indexToBegin;
	int selRowTemp=1;
	int selColTemp=1;
	while((*(text+index) != '\0') && (selRowTemp < mainY-1)) {
		mvwaddch(mainwin,selRowTemp,selColTemp,*(text+index));
		selColTemp++;
		if (*(text+index) == '\n') {
			selRowTemp++;
			selColTemp=1;
		}
		if (selColTemp >= mainX-1) {
			selColTemp=1;
			selRowTemp++;
//			index++;
			wmove(mainwin,selRowTemp,selColTemp);
		}
		index++;
	}


//	box(boxwin,0,0);
	refresh();
//	wrefresh(boxwin);
//	wmove(mainwin,selRow,selCol);
	wmove(mainwin,numLines,selCol);
	if (numLines == 0) {
		wmove(mainwin,++selRow,selCol);
	}
}


char findCharInArray(char* charArray, int selRow, int selCol, int numLines) {
	int indexToBegin=0;
	int numNewLinesFound=0;
	if (numLines > 0) {
		for (int i=0;i<strlen(charArray);i++) {
			if (numNewLinesFound==numLines) {
				indexToBegin=i;
				break;
			}
			if (*(charArray+i)=='\n') {
				numNewLinesFound++;
			}
		}
	}
	
//	*(int*)0 = 0;



	selRow--;
//	selCol++;
	int index=indexToBegin;
	int curRow=0;
	while(curRow < selRow) {
		index++;
		if (*(charArray+index) == '\n') {
			curRow++;
		}
		if (selRow == curRow) {
			break;
		}
	}

	for (int i=0;i<selCol;i++){
		index++;
	}

//	return 'a';

	return *(charArray+index);


}


int charToNewLine(char* text,int textCounter) {
	int returnVal=0;
	while (*(text+textCounter) == 32 ||  *(text+textCounter) == '\n'){
		returnVal++;
		textCounter--;
	}
	return returnVal-1;

}
