#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>

#define M_PI 3.14159265359
#define DISTRICT_NUM 50

struct location{
    char name[100];
    double lats;
    double longs;
};

char username[50];

char* get_current_time() {
   static char time_string[50];
   time_t current_time;
   struct tm *time_info;

   time(&current_time);
   time_info = localtime(&current_time);
   strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", time_info);

   return time_string;
}


double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
    double R = 6371.0;  
    double dlat = (lat2 - lat1) * M_PI / 180.0;
    double dlon = (lon2 - lon1) * M_PI / 180.0;
    double a = sin(dlat/2) * sin(dlat/2) + cos(lat1 * M_PI / 180.0) * cos(lat2 * M_PI / 180.0) * sin(dlon/2) * sin(dlon/2);
    double c = 2 * atan2(sqrt(a), sqrt(1-a));
    double d = R * c;
    return d;
}

double calculateMoney(double km){
    double money = 35;
    if(km < 1) return 0;
    if(km > 80){
        money += (km - 80) * 10.50;
        km = 80;
    }
    if(km > 60){
        money += (km - 60) * 9.0;
        km = 60;
    }
    if(km > 40){
        money += (km - 40) * 8.5;
        km = 40;
    }
    if(km > 20){
        money += (km - 20) * 8;
        km = 20;
    }
    if(km > 10){
        money += (km - 10) * 7;
        km = 10;
    }
    km -= 1;
    money += km * 6.5;

    return money;
    
}

void loadData(int mode , struct location *loc_arr){
   FILE *fp;
   char str[100];
   if(mode == 0)fp = fopen("district.txt", "r");
   else if (mode == 1)fp = fopen("lats.txt", "r");
   else if (mode == 2)fp = fopen("longs.txt", "r");
   if (fp == NULL) {
      printf("Error opening the file!\n");
      return;
   }
   int i = 0;
   while (fgets(str, sizeof(str), fp) != NULL) {
      if(mode == 0){
        strcpy(loc_arr[i].name , strtok(str , "\n"));
      }else{
        char *eptr;
        double data = strtod(str , &eptr);
        if(mode == 1)loc_arr[i].lats = data;
        if(mode == 2)loc_arr[i].longs = data;
      }
       i++;
   }
   fclose(fp);
}

void printTitle(){
    system("cls");
    printf("\033[0;33m=======================================================\n");
    printf("\033[0;31m  _____                  _ _  _      _            \n");
    printf("\033[0;31m |__   __|                | |  \\/  |    | |           \n");
    printf("\033[0;32m    | |_ _ _
_   ____| | \\  / | ___| |
_ _ __ \n");
    printf("\033[0;32m    | | '__/ _` \\ \\ / / _ \\ | |\\/| |/ _ \\ __/ _ \\ '__|\n");
    printf("\033[0;31m    | | | | (_| |\\ V /  __/ | |  | |  __/ ||  __/ |   \n");
    printf("\033[0;32m    |_|_|  \\__,_| \\_/ \\___|_|_|  |_|\\___|\\__\\___|_|   \n");
    printf("\033[0;33m\n=======================================================\033[0;37m\n\n");
}

void printMenu(){
    printf("[1]: Calculate travel expense.\n");
    printf("[2]: Show district list.\n");
    printf("[3]: History\n");
    printf("[4]: Exit\n\n");
    printf("Select command: ");
}

void printDistricList(struct location *loc_arr){
    system("cls");
    printf("\033[0;33m====================================================================\033[0;37m\n\n");
    printf("\033[0;36m8888888b.  d8b          888            d8b          888             \n");
    printf("888  \"Y88b Y8P          888            Y8P          888             \n");
    printf("888    888              888                         888             \n");
    printf("888    888 888 .d8888b  888888 888d888 888  .d8888b 888888 .d8888b  \n");
    printf("888    888 888 88K      888    888P\"   888 d88P\"    888    88K      \n");
    printf("888    888 888 \"Y8888b. 888    888     888 888      888    \"Y8888b. \n");
    printf("888  .d88P 888      X88 Y88b.  888     888 Y88b.    Y88b.       X88 \n");
    printf("8888888P\"  888  88888P'  \"Y888 888     888  \"Y8888P  \"Y888  88888P' \n\n");
    printf("\033[0;33m====================================================================\033[0;37m\n\n");
    int i = 0;
    for(i = 0; i < DISTRICT_NUM ; i++){
        printf("\033[0;32m%d.\033[0;37m%s\n" , i+1 , loc_arr[i].name);
    }
    printf("\n\033[0;31mPress enter to continue..... \033[0;37m");
    getchar();
    getchar();
}

int searchLoc(char *name, struct location *loc_arr){
    int i = 0;
    for(i = 0; i < DISTRICT_NUM ; i++){
        if(!strcmp(loc_arr[i].name , name))return i;
    }
    return -1;
}

void travelExpense(struct location *loc_arr){
    system("cls");

    printf("\033[0;33m====================================================================\033[0;37m\n\n");
    printf("\033[0;36m8888888b.  d8b          888            d8b          888             \n");
    printf("888  \"Y88b Y8P          888            Y8P          888             \n");
    printf("888    888              888                         888             \n");
    printf("888    888 888 .d8888b  888888 888d888 888  .d8888b 888888 .d8888b  \n");
    printf("888    888 888 88K      888    888P\"   888 d88P\"    888    88K      \n");
    printf("888    888 888 \"Y8888b. 888    888     888 888      888    \"Y8888b. \n");
    printf("888  .d88P 888      X88 Y88b.  888     888 Y88b.    Y88b.       X88 \n");
    printf("8888888P\"  888  88888P'  \"Y888 888     888  \"Y8888P  \"Y888  88888P' \n\n");
    printf("\033[0;33m====================================================================\033[0;37m\n\n");
    int i = 0;
    for(i = 0; i < DISTRICT_NUM ; i++){
        printf("\033[0;32m%d.\033[0;37m%s\n" , i+1 , loc_arr[i].name);
    }
    
    printf("\n\033[0;33m===============================\n");
    printf("\n\033[0;32m                  .\n");
    printf("    __            |\\\n");
    printf(" __/__\\___________| \\_\n");
    printf("|   _    |  ,|   ___`-.\n");
    printf("|  /   \\   |___/  /   \\  `-.\n");
    printf("|_| (O) |________| (O) |____|\n");
    printf("   \\___/          \\___/\n\n");
    printf("\n\033[0;33m===============================\n\n\n\033[0;37m");
    int time;
    printf("Please enter estimate idle time(min):");
    scanf("%d" ,&time);
    printf("Please enter the district in string(lower).\n");
    printf("From where (-1 to exit)? :");
    char input[50];
    gets(input);
    int first;
    int index_1 , index_2;
    double distance = 0;
    while(1){
        gets(input);
        if(!strcmp("-1" , input))return;
        index_1 = searchLoc(&input ,loc_arr );
        if(index_1 != -1)break;
        printf("\n\033[0;31mInvalid input!\n\033[0;37m\nTry again:");
    }
    printf("To where?:");
    while(1){
        gets(input);
        if(!strcmp("-1" , input))return;
        index_2 = searchLoc(&input ,loc_arr );
        if(index_2 != -1)break;
        printf("\n\033[0;31mInvalid input!\n\033[0;37m\nTry again:");
    }
    first = index_1;
    distance += calculateDistance(loc_arr[index_1].lats , loc_arr[index_1].longs ,loc_arr[index_2].lats , loc_arr[index_2].longs );
    while(1){
        index_1 = index_2;
        printf("Continue? (y/n):");
        gets(input);
        if(!strcmp("n", input))break;
            printf("To where?:");
        while(1){
            gets(input);
            if(!strcmp("-1" , input))return;
            index_2 = searchLoc(&input ,loc_arr );
            if(index_2 != -1)break;
            printf("\n\033[0;31mInvalid input!\n\033[0;37m\nTry again:");
        }
        distance += calculateDistance(loc_arr[index_1].lats , loc_arr[index_1].longs ,loc_arr[index_2].lats , loc_arr[index_2].longs );
    }

    printf("\nFrom \033[0;32m%s \033[0;37mto \033[0;32m%s \033[0;37mis \033[0;32m%.2f \033[0;37mkm\n" , loc_arr[first].name , loc_arr[index_2].name , distance);
    double money = calculateMoney(distance) + (time * 3);
    printf("Estimated Price:\033[0;33m %.0f \033[0;37mbaht\n" , money);

    FILE *fp;
    char str[100];
    fp = fopen("logs.txt" , "a");
    if (fp == NULL) {
        printf("Error opening file!\n");
        return 1;
    }
    fprintf(fp , "\n\nAt %s \n%s travel from %s to %s\nIn a distance of %.2fkm\nEstimated Price of %.0f baht" , get_current_time() , username , loc_arr[first].name , loc_arr[index_2].name , distance ,money );
    fclose(fp);

    printf("\n\033[0;31mPress enter to continue..... \033[0;37m");
    getchar();
}

void printHistory(){
    system("cls");
    printf("================\033[0;33m History \033[0;37m===============\n");
    FILE *fp;
    char str[100];
    fp = fopen("logs.txt", "r");
    if (fp == NULL) {
      printf("Error opening the file!\n");
      return;
    }

    while (fgets(str, sizeof(str), fp) != NULL) {
     printf("%s",str);
    }
    fclose(fp);
    printf("\n\033[0;31mPress enter to continue..... \033[0;37m");
    getchar();
    getchar();
}

int main(){
    printf("Enter your username: ");
    scanf("%s" , &username);

    struct location *loc_arr;
    loc_arr = (struct location*)malloc(50 * sizeof(struct location));
    loadData(0 , loc_arr);
    loadData(1 , loc_arr);
    loadData(2 , loc_arr);
    
    printTitle();
    while(1){
        printMenu();
        int command;
        scanf("%d" , &command);
        if(command == 1){
            travelExpense(loc_arr);
            printTitle();
        }else if(command == 2){
            printDistricList(loc_arr);
            printTitle();
            
        }else if(command == 3){
            printHistory();
            printTitle();
        }else if(command == 4){
            break;
        }else{
            printf("\033[0;31mInvalid Command!\n\n\033[0;37m");
        }
    }
    
    return 0;
}