//Make By PINK
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>
#include <curl/curl.h>

// ANSI Color Codes
#define NC "\033[0m"
#define LRED "\033[1;31m"
#define LGREEN "\033[1;32m"
#define YELLOW "\033[1;33m"
#define PURPLE "\033[1;35m"
#define LBLUE "\033[1;36m"

// Constants
const char *PASSWORD_LIST_URL = "https://raw.githubusercontent.com/JJLPZ/Login-key/refs/heads/main/keytxt";
const char *INPUT_DIR = "/sdcard/Download/JWH/MAP/INPUT_FILE";
const char *DECRYPT_DIR = "/sdcard/Download/JWH/MAP/DECRYPT";
const char *ENCRYPT_DIR = "/sdcard/Download/JWH/MAP/ENCRYPT";
const char *PAKMAP_CMD = "./pakmap";

// Memory structure for libcurl
struct MemoryStruct {
    char *memory;
    size_t size;
};

// CURL callback to write data
static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t total_size = size * nmemb;
    struct MemoryStruct *mem = (struct MemoryStruct *)userp;

    char *ptr = realloc(mem->memory, mem->size + total_size + 1);
    if (!ptr) {
        fprintf(stderr, "Not enough memory to allocate!\n");
        return 0;
    }

    mem->memory = ptr;
    memcpy(&(mem->memory[mem->size]), contents, total_size);
    mem->size += total_size;
    mem->memory[mem->size] = 0;

    return total_size;
}

// Function to fetch password list
char *fetch_password_list() {
    CURL *curl;
    CURLcode res;
    struct MemoryStruct chunk = {malloc(1), 0};

    curl_global_init(CURL_GLOBAL_ALL);
    curl = curl_easy_init();

    if (!curl) {
        fprintf(stderr, "%sFailed to initialize CURL%s\n", LRED, NC);
        return NULL;
    }

    curl_easy_setopt(curl, CURLOPT_URL, PASSWORD_LIST_URL);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);

    res = curl_easy_perform(curl);
    if (res != CURLE_OK) {
        fprintf(stderr, "%sCURL error: %s%s\n", LRED, curl_easy_strerror(res), NC);
        free(chunk.memory);
        curl_easy_cleanup(curl);
        curl_global_cleanup();
        return NULL;
    }

    curl_easy_cleanup(curl);
    curl_global_cleanup();
    return chunk.memory;
}

// Password verification function
int authenticate_user() {
    char *password_list = fetch_password_list();
    if (!password_list) {
        fprintf(stderr, "%sFailed to fetch password list.%s\n", LRED, NC);
        return 0;
    }

    char password[256];
    printf("%sEnter Password: %s", YELLOW, NC);
    scanf("%s", password);

    if (strstr(password_list, password)) {
        printf("%sAuthentication successful!%s\n", LGREEN, NC);
        free(password_list);
        return 1;
    } else {
        printf("%sAuthentication failed!%s\n", LRED, NC);
        free(password_list);
        return 0;
    }
}

// Directory setup function
void create_directories() {
    mkdir("/sdcard/Download/JWH/MAP", 0755);
    mkdir(INPUT_DIR, 0755);
    mkdir(DECRYPT_DIR, 0755);
    mkdir(ENCRYPT_DIR, 0755);
}

// Function to list .pak files in a directory
int list_files(const char *dir_path, char files[][256], int max_files) {
    DIR *dir = opendir(dir_path);
    if (!dir) {
        fprintf(stderr, "%sCannot open directory: %s%s\n", LRED, dir_path, NC);
        return 0;
    }

    struct dirent *entry;
    int count = 0;
    while ((entry = readdir(dir)) && count < max_files) {
        if (strstr(entry->d_name, ".pak")) {
            snprintf(files[count], 256, "%s/%s", dir_path, entry->d_name);
            count++;
        }
    }
    closedir(dir);
    return count;
}

// Decrypt map function
void decrypt_map(const char *file) {
    char cmd[512];
    snprintf(cmd, sizeof(cmd), "%s %s %s/%s", PAKMAP_CMD, file, DECRYPT_DIR, strrchr(file, '/') + 1);
    if (system(cmd) == 0) {
        printf("%sDecrypt successful! File saved in: %s%s\n", LGREEN, DECRYPT_DIR, NC);
        unlink(file);
    } else {
        printf("%sDecrypt failed!%s\n", LRED, NC);
    }
}

// Encrypt map function
void encrypt_map(const char *file) {
    char cmd[512];
    snprintf(cmd, sizeof(cmd), "%s %s %s/%s", PAKMAP_CMD, file, ENCRYPT_DIR, strrchr(file, '/') + 1);
    if (system(cmd) == 0) {
        printf("%sEncrypt successful! File saved in: %s%s\n", LGREEN, ENCRYPT_DIR, NC);
        unlink(file);
    } else {
        printf("%sEncrypt failed!%s\n", LRED, NC);
    }
}

// Progress bar simulation
void progress_bar(int duration) {
    for (int i = 0; i <= duration; i++) {
        printf("\rProgress: [%-50s] %d%%", "##################################################" + 50 - (i * 50 / duration), (i * 100 / duration));
        fflush(stdout);
        sleep(1);
    }
    printf("\n");
}

// Menu for decrypting maps
void decrypt_menu() {
    char files[10][256];
    int file_count = list_files(INPUT_DIR, files, 10);

    if (file_count == 0) {
        printf("%sNo .pak files found in %s%s\n", LRED, INPUT_DIR, NC);
        return;
    }

    printf("Select a file to decrypt:\n");
    for (int i = 0; i < file_count; i++) {
        printf("[%d] %s\n", i + 1, files[i]);
    }
    printf("[0] Quit\n");

    int choice;
    printf("Enter your choice: ");
    scanf("%d", &choice);

    if (choice > 0 && choice <= file_count) {
        decrypt_map(files[choice - 1]);
        progress_bar(3);
    }
}

// Menu for encrypting maps
void encrypt_menu() {
    char files[10][256];
    int file_count = list_files(INPUT_DIR, files, 10);

    if (file_count == 0) {
        printf("%sNo .pak files found in %s%s\n", LRED, INPUT_DIR, NC);
        return;
    }

    printf("Select a file to encrypt:\n");
    for (int i = 0; i < file_count; i++) {
        printf("[%d] %s\n", i + 1, files[i]);
    }
    printf("[0] Quit\n");

    int choice;
    printf("Enter your choice: ");
    scanf("%d", &choice);

    if (choice > 0 && choice <= file_count) {
        encrypt_map(files[choice - 1]);
        progress_bar(3);
    }
}

// Main menu
void main_menu() {
    int choice;
    while (1) {
        printf("\n%sMain Menu:%s\n", PURPLE, NC);
        printf("[1] Decrypt Map\n");
        printf("[2] Encrypt Map\n");
        printf("[3] Exit\n");
        printf("Enter your choice: ");
        scanf("%d", &choice);

        switch (choice) {
            case 1:
                decrypt_menu();
                break;
            case 2:
                encrypt_menu();
                break;
            case 3:
                printf("%sExiting...%s\n", LGREEN, NC);
                return;
            default:
                printf("%sInvalid choice!%s\n", LRED, NC);
        }
    }
}

// Main function
int main() {
    printf("%sInitializing program...%s\n", LGREEN, NC);
    create_directories();

    if (!authenticate_user()) {
        printf("%sAuthentication failed. Exiting.%s\n", LRED, NC);
        return 1;
    }

    main_menu();
    return 0;
}