#include  <stdio.h>
#include  <windows.h>
#include  <conio.h >
#include  <string.h >

            HANDLE console;
                  
            void gotoxy(short x, short y) {COORD pos = {x, y};
                        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);}
                                             
                                             
            void hidecursor(){   
                        HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
                           CONSOLE_CURSOR_INFO info;  
    				        info.dwSize = 100;  
	 				info.bVisible = FALSE;
    				        SetConsoleCursorInfo(consoleHandle, &info);}

            void draw_frame(int x, int y, int width, int height) {
                                 
                        int i, j;
                        gotoxy(x, y);
                        printf("%c", 201); // top-left corner
                        for (i = 1; i < width; i++) {
                        printf("%c", 205);} // horizontal line
                  
                        printf("%c", 187); // top-right corner
                        for (i = 1; i < height; i++) {
                        gotoxy(x, y + i);
                        printf("%c", 186); // vertical line
                        gotoxy(x + width, y + i);
                        printf("%c", 186);} // vertical line
    
                        gotoxy(x, y + height);
                        printf("%c", 200); // bottom-left corner
                        for (i = 1; i < width; i++) {
                        printf("%c", 205);} // horizontal line
    
                        printf("%c", 188);} // bottom-right corner

            struct our_window {
                        int position_x;
                        int position_y;
                        int width;
                        int height;
                        int size;
                        int selected_item_position;
                        int position;
                        char active;
                        char visible;
                        int cursor_position;
                        int max_position;
                        char names[60][40];
                        char color_scheme;};

           
                        struct our_window new_window;
                        struct our_window help_window;
                        struct our_window modify_window;
                        struct our_window additional_window; 

                        char temporary[20][40];
                        char help_options[10][40];
                        char add_window[40];
                        char add_window_2[40];
                        char shopping_list[3][3][40];


            void prepare_window(struct our_window *new_window, int pos_x, int pos_y, int width, 
                        int height, char names_count,  char *names,char sch,char act,char wid){

                        new_window->position_x=pos_x;
                        new_window->position_y=pos_y;
                        new_window->height=height;
                        new_window->width=width;
                        new_window->size=names_count;
                        new_window->selected_item_position=0;
                        new_window->cursor_position=0;
                        new_window->color_scheme=0;
                        new_window->max_position=names_count-height;
                        new_window->active=act;                        
                        new_window->visible=wid;
                        for(int i=0;i<60;i++){
                        for(int j=0;j<40;j++){new_window->names[i][j]='\0';}}
                        for(int i=0,k=0,j=0;i<200;i++,k++){
                        if(names[k]!=36){new_window->names[j][i]=names[k];
                        }else{    
                        new_window->names[j][i]='\0';    
                        if(i<40){k+=40-i-1;} 
                        i=-1;j++;if(j==names_count){break;}}}}

            void hide_window(struct our_window target_window){

			// set the text color to black
			SetConsoleTextAttribute(console, 0x00);
			for(int i=target_window.position_x;i<target_window.width+target_window.position_x+1;i++){
			for(int j=target_window.position_y;j<target_window.height+target_window.position_y+1;j++){
			// move the cursor to the current position
			gotoxy(i, j);
			// print a space character to hide the contents of the window
			printf("%c", 32);}}} 

              void display_window(struct our_window target_window){
                        if(target_window.visible==1){
                        SetConsoleTextAttribute(console, 0x07);
                        struct our_window t=target_window;
                        draw_frame(t.position_x,t.position_y,t.width,t.height);
			// set the text color to white
			 
			int amount_to_display = 0;
    
			// check if the number of entries is greater than or equal to the size of the frame, 
			// or smaller, to know how many entries to display
			if(target_window.size >= target_window.height){
			amount_to_display = target_window.height - 1;
			} else {
			amount_to_display = target_window.size;}
    
    			
			// display the entries
			for(int i = 0; i < amount_to_display; i++){
			for(int j = 0; j < target_window.width - 1; j++){
			
			// move the cursor to the current position            
			gotoxy(target_window.position_x + 1 + j, target_window.position_y + 1 + i);
			
			// print the current entry            
			printf("%c", target_window.names[i][j]);}}

			
			// check if the cursor should be displayed
			if(target_window.active == 1){
			
			// set the text color to white on dark gray background        
			SetConsoleTextAttribute(console, 0x70);
			for(int j = 0; j < target_window.width - 1; j++){
			
			// move the cursor to the current position            
			gotoxy(target_window.position_x+1+j,target_window.position_y + 1 + target_window.cursor_position);
			
			// print the current entry with cursor
			printf("%c", target_window.names[target_window.position][j]);}}}}



              void init(){
                        strcpy(temporary[0],"Andrew$");
                        strcpy(temporary[1],"John$");
                        strcpy(temporary[2],"Tom$");
                        strcpy(temporary[3],"Lucas$");
                        strcpy(temporary[4],"Joseph$");
                        strcpy(temporary[5],"Henry$");
                        strcpy(temporary[6],"Monica$");
                        strcpy(shopping_list[0][0],"Tonic$");
                        strcpy(shopping_list[0][1],"Chineese soup$");
                        strcpy(shopping_list[0][2],"Potatoes$");
		
                        strcpy(shopping_list[1][0],"Butter$");
                        strcpy(shopping_list[1][1],"Water$");
                        strcpy(shopping_list[1][2],"Smietana$");
		
                        strcpy(shopping_list[2][0],"Rzodkiewka$");
                        strcpy(shopping_list[2][1],"Cebula$");
                        strcpy(shopping_list[2][2],"Ziemniaki$");
                        
                        strcpy(help_options[0],"p - This window$");
                        strcpy(help_options[1],"z - Save to file$");
                        strcpy(help_options[2],"w - Read from file$");
                        strcpy(help_options[3],"e - Edit$");
                        
                        hidecursor();
                        console = GetStdHandle(STD_OUTPUT_HANDLE);
                        
                        prepare_window(&new_window,36,7,30,5,7,&temporary[0][0],0,1,1);
                        prepare_window(&help_window,38,8,25,4,4,&help_options[0][0],0,0,0);
                        prepare_window(&modify_window,30,3,30,2,1,&add_window[0],0,1,0);
                        prepare_window(&additional_window,30,8,30,5,3,&shopping_list[0][0][0],0,0,0);
                          
                        display_window(new_window);}


              void move_cursor_down(struct our_window *target_window) {
                        // if the cursor is not pointing to the last element
                        if (target_window->position < target_window->size - 1) {

                        // if the cursor position is not on the border of the frame height
                        if (target_window->cursor_position < target_window->height - 2) {
                        SetConsoleTextAttribute(console, 0x07);

                        // display the name of the element where the cursor is currently pointing to
                        for (int i = 0; i < target_window->width - 1; i++) {
                        gotoxy(target_window->position_x + 1 + i, target_window->position_y +
                        1 + target_window->cursor_position);
                        printf("%c", target_window->names[target_window->position][i]);}
            

                        // move the cursor down by one position
                        target_window->position++;
                        target_window->cursor_position++;

                        SetConsoleTextAttribute(console, 0x70);

                        // display the name of the element where the cursor is currently 
                        //pointing to, with highlighted text
                        for (int i = 0; i < target_window->width - 1; i++) {
                        gotoxy(target_window->position_x + 1 + i, target_window->position_y + 1
                        + target_window->cursor_position);
                        printf("%c", target_window->names[target_window->position][i]);}
                        
                        } else {

                        // move the cursor down by one position
                        target_window->position++;

                        int tmp = target_window->height - 2;

                        // calculate the starting position for displaying elements, 
                        // and display the elements on the window
                        int start = target_window->position - tmp;

                        SetConsoleTextAttribute(console, 0x07);

                        for (int j = 0; j < target_window->height - 1; j++) {
                        for (int i = 0; i < target_window->width - 1; i++) {
                        gotoxy(target_window->position_x + i + 1, target_window->position_y + j + 1);

                        // highlight the current cursor position
                        if (j == target_window->height - 2) {
                        SetConsoleTextAttribute(console, 0x70);}
                    
                        printf("%c", target_window->names[start + j][i]);}}}}}


              void move_cursor_up(struct our_window *target_window){
                        if (target_window->position > 0){
                        if (target_window->cursor_position > 0){
                        SetConsoleTextAttribute(console, 0x07);
                        for (int i = 0; i < target_window->width - 1; i++){
                        gotoxy(target_window->position_x + 1 + i, target_window->position_y + 
                        1 + target_window->cursor_position);
                        printf("%c", target_window->names[target_window->position][i]);}
                        
                        target_window->position = target_window->position - 1;
                        target_window->cursor_position--;
                        SetConsoleTextAttribute(console, 0x70);
                        for (int i = 0; i < target_window->width - 1; i++){
                        gotoxy(target_window->position_x + 1 + i, target_window->position_y +
                         1 + target_window->cursor_position);
                        printf("%c", target_window->names[target_window->position][i]);}

                        }else{
                        target_window->position--;
                        int tmp = target_window->height - 2;
                        int start = target_window->position;
                        
                        SetConsoleTextAttribute(console, 0x70);
                        for (int j = 0; j < target_window->height - 1; j++){
                        for (int i = 0; i < target_window->width - 1; i++){
                        gotoxy(target_window->position_x + i + 1, target_window->position_y + j + 1);
                        if (j > 0){ SetConsoleTextAttribute(console, 0x07); }
                        printf("%c", target_window->names[start + j][i]);}}}}}

int change_entry(char *ptr, int poz_x, int poz_y, int length){
          
             
             char text[60];
             char *ptr2;
             ptr2=ptr;
             for(int i=0;i<length;i++){text[i]=*ptr2;ptr2++;}
             int position=0;
             hidecursor();
             SetConsoleTextAttribute(console, 0x17);
             
			 for(int i=0;i<length;i++){gotoxy(poz_x+i,poz_y);printf("%c",text[i]);}
			 
			 
			 
	
             SetConsoleTextAttribute(console, 0x70);
             gotoxy(poz_x,poz_y);
             printf("%c",text[position]);
             gotoxy(poz_x,poz_y);

             int char1 = 0;
             int char2 = 0;

             while (1)
             {
                  char1 = getch();

                  if (char1 == 224)
                  {
                  char2 = getch();

                  switch (char2)
                  {
               
                  case 75:
                          if(position>0){
                          gotoxy(position+poz_x,0+poz_y);       	
                          SetConsoleTextAttribute(console, 0x17);
                          printf("%c",text[position]);
                          SetConsoleTextAttribute(console, 0x70);
                          position--;gotoxy(position+poz_x,0+poz_y); 
                          printf("%c",text[position]);}
                          break;			 
			 		 

                case 77:
                  
                          if(position<length-1){ 
                          gotoxy(position+poz_x,0+poz_y);
                          SetConsoleTextAttribute(console, 0x17);
                          printf("%c",text[position]);
                          SetConsoleTextAttribute(console, 0x70);
                          position++;gotoxy(position+poz_x,0+poz_y); 
                          printf("%c",text[position]);}
                          break;
                    
                          }
                  }else{
   

                    if(position<length && char1!=8  && char1!=13){
                          gotoxy(position+poz_x,0+poz_y);
                          text[position]=char1;
                          SetConsoleTextAttribute(console, 0x17);
                          printf("%c",char1);
                          if(position<length-1){
                          position++;
                          SetConsoleTextAttribute(console, 0x70);
                          gotoxy(position+poz_x,0+poz_y);
                          printf("%c",text[position]);
                  

                  }else{
                                 gotoxy(position+poz_x,0+poz_y);
                                 SetConsoleTextAttribute(console, 0x70);
                                 printf("%c",text[position]);}}
			 
                                 if(char1==8 && position>0){
			
                                            if(position==length-1){
                                            text[position]=32;
                                            SetConsoleTextAttribute(console, 0x17);
                                            gotoxy(position+poz_x,0+poz_y);
                                            printf("%c",text[position]);
                                            SetConsoleTextAttribute(console, 0x70);
                                            gotoxy(position+poz_x,0+poz_y);
                                            position--;
                                            gotoxy(position+poz_x,0+poz_y);
                                            printf("%c",text[position]);
                                            }else{
                                            
                                            text[position]=32;
                                            SetConsoleTextAttribute(console, 0x17);
                                            printf("%c",text[position]);
                                            SetConsoleTextAttribute(console, 0x70);
                                            position--;
                                            gotoxy(position+poz_x,0+poz_y);
                                            printf("%c",text[position]);}}
			 
			 
                    if(char1==8 && position==0){
                                            text[position]=32;
                                            gotoxy(position+poz_x,0+poz_y);
                                            SetConsoleTextAttribute(console, 0x70);
                                            printf("%c",text[position]);}
		
                    if(char1==27){return 0;}
                    if(char1==13){
                                            SetConsoleTextAttribute(console, 0x70);
                                            for(int i=0;i<length;i++){
                                            gotoxy(i+poz_x,poz_y);
                                            printf("%c",text[i]);
                                            *ptr=text[i];ptr++;}
                                            return 1;}	
			 	
                    }



                    gotoxy(position+poz_x,0+poz_y);
}}


void add_new_item(){
                  
		SetConsoleTextAttribute(console, 0x07);
		modify_window.visible=1;
		modify_window.position_x=new_window.position_x;
		modify_window.position_y=new_window.position_y+2;
		gotoxy(new_window.position_x+1,new_window.position_y+1);
		printf("%s","        Write new name     ");
		display_window(modify_window);
		new_window.active=0;
								
		for(int i=0;i<39;i++){add_window[i]='\0';add_window_2[i]='\0';}
		//display_window(&add_window);
						
		// jeśli nasza funkcja "zmien_wpis" zwraca nowy łacuch znaków
		if(change_entry(&add_window[0],new_window.position_x+1,new_window.position_y+3,29)==1){                
						
			hide_window(modify_window);
	
			int changed=0;
			strcpy(temporary[new_window.size],"");
			for(int u=0;u<39;u++){
			if(add_window[u]>30 && add_window[u]<123){
			add_window_2[u]=add_window[u];
			temporary[new_window.size][u]=add_window[u];
			}else{
								
			add_window_2[u]=36;add_window_2[u+1]='\0';
			strcpy(temporary[new_window.size],add_window_2);
			SetConsoleTextAttribute(console, 0x70);
			

			//kopiujemy zapis z tablicy "okno_dodawania2" do naszego 
			//obiektu "new_window.names"(tablica z łacuchami znaków)
			for(int k=0;k<u;k++){  
					 new_window.names[new_window.size][k]=add_window_2[k];}
					 new_window.size++;
					 break;}}
							
					  }else{
					 hide_window(modify_window);} // ukrywamy okno dodawania
					 for(int u=0;u<40;u++){add_window[u]=32;
					 add_window_2[u]=32;}
				                     
					 add_window[39]='\0';
					 add_window_2[39]='\0';
					 // resetujemy ustawienia naszego okna
					 prepare_window(&modify_window,30,3,30,2,1,&add_window[0],0,1,0);
					 new_window.active=1;
								    
					 display_window(new_window);}


void remove_item(){

                  char temporary_2[60][40]; // Declare a two-dimensional array of characters

                  // If there are elements to remove
                  if (new_window.size > 0) {

                  // If there are more than one elements to copy
                  if (new_window.size > 1) {

                  // Copy values from the object new_window.names to the temporary array temporary_2
                  for (int i = 0, k = 0; i < new_window.size; i++) {
                  if (i != new_window.position) {
                  strcpy(temporary_2[k], new_window.names[i]);
                  k++;}}
            

                  // Reset the current position of the element
                  new_window.position = 0;
                  new_window.cursor_position = 0;

                  // Decrement the number of elements
                  new_window.size--;

                  // Copy values from the temporary array temporary_2 back to the original array new_window.names
                  for (int i = 0; i < new_window.size; i++) {
                  strcpy(new_window.names[i], temporary_2[i]);}
            

                  // Reset the appearance of the window
                  hide_window(new_window);
                  display_window(new_window);

                  }else {    // If there is only one element

                  new_window.size--;
                  strcpy(new_window.names[0], "                           ");

                  // Reset the appearance of the window
                  hide_window(new_window);
                  display_window(new_window);}}}


void sort(int *asc_desc){


    char temporary_2[60][40];
    
    // Replace spaces with characters that the "strcmp" function can handle
    for (int i = 0; i < new_window.size; i++) {
        for (int j = 0; j < 40; j++) {
            if (new_window.names[i][j] == 32) {
                new_window.names[i][j] = 36;
            }
        }
    }
    
    char tmp_tab[40];

    if (*asc_desc == 0) { // if ascending sort is selected

        // Sort the "new_window.names" array in ascending order
        for (int i = 0; i < new_window.size; i++) {
            for (int j = 0; j < new_window.size - 1; j++) {
                if ((strcmp(new_window.names[j], new_window.names[j+1])) > 0) {
                    strcpy(tmp_tab, new_window.names[j]);
                    strcpy(new_window.names[j], "                           ");
                    strcpy(new_window.names[j], new_window.names[j+1]);
                    strcpy(new_window.names[j+1], "                         ");
                    strcpy(new_window.names[j+1], tmp_tab);
                }
            }
        }

        // Replace the characters with spaces again
        for (int i = 0; i < new_window.size; i++) {
            for (int j = 0; j < 40; j++) {
                if (new_window.names[i][j] == 36) {
                    new_window.names[i][j] = 32;
                }
            }
        }
        
        hide_window(new_window);
        display_window(new_window);
        *asc_desc = 1; // set sort order to ascending

    } else { // if descending sort is selected

        // Sort the "new_window.names" array in descending order
        for (int i = 0; i < new_window.size; i++) {
            for (int j = 0; j < new_window.size - 1; j++) {
                if ((strcmp(new_window.names[j], new_window.names[j+1])) < 0) {
                    strcpy(tmp_tab, new_window.names[j]);
                    strcpy(new_window.names[j], "                             ");
                    strcpy(new_window.names[j], new_window.names[j+1]);
                    strcpy(new_window.names[j+1], "                           ");
                    strcpy(new_window.names[j+1], tmp_tab);
                }
            }
        }

        // Replace the characters with spaces again
        for (int i = 0; i < new_window.size; i++) {
            for (int j = 0; j < 40; j++) {
                if (new_window.names[i][j] == 36) {
                    new_window.names[i][j] = 32;
                }
            }
        }
        
        hide_window(new_window);
        display_window(new_window);
        *asc_desc = 0; // set sort order to descending
    }}


void save_data(){              
                     FILE *ptr_file;
                     ptr_file=fopen("names.dat","wb");
          
                     fprintf(ptr_file,"%d\n",new_window.size);
                     for(int i=0;i<new_window.size;i++){
          
                     for(int j=0;j<29;j++){
                     fprintf(ptr_file,"%c",new_window.names[i][j]);}
		  	
                     fprintf(ptr_file,"\n");}
	
                     fclose(ptr_file);}


void read_data(){
		        FILE *ptr_file;
		        ptr_file=fopen("names.dat","rb");
		        int size=0;
		        char tmp;
		        fscanf(ptr_file,"%d\n",&size);
		        for(int i=0;i<size;i++){
		        for(int j=0;j<29;j++){fscanf(ptr_file,"%c",&new_window.names[i][j]);}
		        new_window.names[i][29]='\0';
	
		        fscanf(ptr_file,"\n",&tmp);}
	     
		        new_window.size=size;
		        new_window.position=0;
		        new_window.cursor_position=0;
		        hide_window(new_window);
		        display_window(new_window);
		        fclose(ptr_file);
		        }     

void display_content(struct our_window target_window){
                        if(target_window.visible==1){
                        SetConsoleTextAttribute(console, 0x07);
                        struct our_window t=target_window;
                        //draw_frame(t.position_x,t.position_y,t.width,t.height);
			// set the text color to white
			 
			int amount_to_display = 0;
    
			// check if the number of entries is greater than or equal to the size of the frame, 
			// or smaller, to know how many entries to display
			if(target_window.size >= target_window.height){
			amount_to_display = target_window.height - 1;
			} else {
			amount_to_display = target_window.size;}
    
    			
			// display the entries
			for(int i = 0; i < amount_to_display; i++){
			for(int j = 0; j < target_window.width - 1; j++){
			
			// move the cursor to the current position            
			gotoxy(target_window.position_x + 1 + j, target_window.position_y + 1 + i);
			
			// print the current entry            
			printf("%c", target_window.names[i][j]);}}

			
			// check if the cursor should be displayed
			if(target_window.active == 1){
			
			// set the text color to white on dark gray background        
			SetConsoleTextAttribute(console, 0x70);
			for(int j = 0; j < target_window.width - 1; j++){
			
			// move the cursor to the current position            
			gotoxy(target_window.position_x+1+j,target_window.position_y + 1 + target_window.cursor_position);
			
			// print the current entry with cursor
			printf("%c", target_window.names[target_window.position][j]);}}}}