/*
 * epd_s3.cpp
 *
 *  Created on: 14-Nov-2023
 *      Author: Shruthi KR
 */

#include <stdio.h>
#include "string.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_sleep.h"
// #include "color/gdew075c64.h" // this library is for 7.5~BWR EPD
#include "color/gdeq042Z21.h" // this library is for 4.2~BWR EPD
#include "esp_spiffs.h"
#include "Config.h"
EpdSpi io;
Gdeq042Z21 display(io);
#include <Fonts/FreeMono12pt7b.h>
#include <Fonts/FreeMonoBold100pt7b.h>
void display_image_4_2(void);
void display_text_4_2(void);
void display_image_7_5(void);
void display_text_7_5(void);
extern char black_file_path[256];
extern char red_file_path[256];

#define IMAGE_SIZE (400 * 300 / 8)
#define TAG "FILE_PARSER"
void delay(uint32_t millis)
{
    vTaskDelay(millis / portTICK_PERIOD_MS);
}

extern "C" {
    void enter_deep_sleep_mode(void);
    void set_led_blink_multi(bool red1, bool green1, bool blue1, 
                         bool red2, bool green2, bool blue2, 
                         int blink_interval_ms);
}



extern "C" void epd_s3_main(void)
{

    gpio_set_direction(BLUE, GPIO_MODE_OUTPUT);
    display_image_4_2();

}

bool read_and_parse_file_decimal(const char* filepath, unsigned char* array, size_t array_size) {
    FILE* file = fopen(filepath, "r");
    if (file == NULL) {
        ESP_LOGE(TAG, "Failed to open file: %s", filepath);
        return false;
    }

    size_t index = 0;
    int value;

    while (index < array_size && fscanf(file, "%d,", &value) == 1) {
        array[index] = (unsigned char)(value & 0xFF);
        index++;
    }

    fclose(file);

    if (index != array_size) {
       // set_led_blink_multi(true, false, false,false, false, false,300);
        ESP_LOGE(TAG, "Failed to read full file: %s. Read %d bytes, expected %d", 
                 filepath, index, array_size);
        return false;
    }

    ESP_LOGI(TAG, "Successfully read and parsed file (decimal format): %s", filepath);
    return true;
}

bool read_and_parse_file_hex(const char* filepath, unsigned char* array, size_t array_size) {
    FILE* file = fopen(filepath, "r");
    if (file == NULL) {
       // set_led_blink_multi(true, false, false,false, false, false,300);
        ESP_LOGE(TAG, "Failed to open file: %s", filepath);
        return false;
    }

    size_t index = 0;
    unsigned int value;

    while (index < array_size) {
        if (fscanf(file, " 0X%2X,", &value) == 1) {
            array[index] = (unsigned char)value;
            index++;
        } else {
            // Skip any non-matching characters
            if (fgetc(file) == EOF) break;
        }

        if (feof(file)) break;
    }

    fclose(file);

    if (index != array_size) {
        //set_led_blink_multi(true, false, false,false, false, false,300);
        ESP_LOGE(TAG, "Failed to read full file: %s. Read %d bytes, expected %d", 
                 filepath, index, array_size);
        return false;
    }

    ESP_LOGI(TAG, "Successfully read and parsed file (hex format): %s", filepath);
    return true;
}

bool detect_format_and_parse_file(const char* filepath, unsigned char* array, size_t array_size) {
    FILE* file = fopen(filepath, "r");
    if (file == NULL) {
        ESP_LOGE(TAG, "Failed to open file: %s", filepath);
        return false;
    }

    char buffer[10];
    bool is_hex_format = false;

    // Read the first few characters to detect the format
    if (fgets(buffer, sizeof(buffer), file) != NULL) {
        if (strstr(buffer, "0X") != NULL || strstr(buffer, "0x") != NULL) {
            is_hex_format = true;
        }
    }

    fclose(file);

    // Call the appropriate parsing function based on the detected format
    if (is_hex_format) {
        ESP_LOGI(TAG, "Detected hex format, using hex parser");
        return read_and_parse_file_hex(filepath, array, array_size);
    } else {
        ESP_LOGI(TAG, "Detected decimal format, using decimal parser");
        return read_and_parse_file_decimal(filepath, array, array_size);
    }
}

void print_array_sample(const unsigned char* array, size_t array_size, const char* array_name) {
    ESP_LOGI(TAG, "Printing first 20 bytes of %s:", array_name);
    for (int i = 0; i < 20 && i < array_size; i++) {
        printf("0X%02X,", array[i]);
        if ((i + 1) % 10 == 0) printf("\n");
    }
    printf("\n");
}


void display_image_4_2() {
    gpio_set_level(BLUE, 1);
    
    unsigned char *gImage_respectb = (unsigned char*)heap_caps_malloc(IMAGE_SIZE, MALLOC_CAP_8BIT);
    unsigned char *gImage_respectr = (unsigned char*)heap_caps_malloc(IMAGE_SIZE, MALLOC_CAP_8BIT);

    if (!gImage_respectb || !gImage_respectr) {
        ESP_LOGE(TAG, "Failed to allocate memory for image buffers");
        goto cleanup;
    }

    if (!detect_format_and_parse_file(black_file_path, gImage_respectb, IMAGE_SIZE) ||
        !detect_format_and_parse_file(red_file_path, gImage_respectr, IMAGE_SIZE)) {
        ESP_LOGE(TAG, "Failed to read image files");
        goto cleanup;
    }

    print_array_sample(gImage_respectb, IMAGE_SIZE, "gImage_respectb");
    print_array_sample(gImage_respectr, IMAGE_SIZE, "gImage_respectr");

    display.init();
    display.drawBitmap(0, 0, gImage_respectb, 400, 300, EPD_BLACK);
    display.drawBitmap(0, 0, gImage_respectr, 400, 300, EPD_RED);
    display.update();
   // enter_deep_sleep_mode();
   

cleanup:
    set_led_blink_multi(true, false, false,false, false, false,300);
    if (gImage_respectb) heap_caps_free(gImage_respectb);
    if (gImage_respectr) heap_caps_free(gImage_respectr);
}
