#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

#include "FreeRTOS.h"
#include "esp_cpu.h"
#include "esp_timer.h"

#include "drivers/fs/fs.hpp"
#include "boot/entry.hpp"
#include "boot/answer_code.hpp"
#include "lib/runtime/RT.hpp"

extern Handler_vfs boot_handler;

void log_result(int res, char *service_name){ 
    if (res == OS_OK) {
        printf("[  \033[0;32mOK\033[0m  ] %s\n", service_name);
    } else {
        char *err_text = "Error";
        const char *msg = get_error(res);
        if (strncmp(msg, err_text, 5) == 0) {
            printf("[  \033[0;31mEROR\033[0m  ] %s initialization: %s (%d)\n", service_name, msg, res);
        } else {
            printf("[  \033[0;33mWARN\033[0m  ] %s initialization: %s (%d)\n", service_name, msg, res);
        }
    }
}

Result test_fn(descriptor *fn) {
    /*printf("Вызов функции %s\n", fn->name);
    fn->ret.int_v = 42;*/
    return {OS_OK, *fn};
}

int main_entry()
{
    printf("Free IRAM: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT | MALLOC_CAP_EXEC));
    printf("Largest IRAM block: %d bytes\n", heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT | MALLOC_CAP_EXEC));

    //printf("\033[2J\033[H");
    printf("OS started\n");

    log_result(init_fs(), "VFS");

    mount(MOUNT_HANDLER, boot_handler.path, boot_handler.path, &boot_handler);

    /*

    boot_handler.link_function("/test_fn", test_fn);
    
    int fd = open("/boot/test_fn", O_RDWR | O_CREAT | O_TRUNC);
    if (fd >= 0) {
        //write(fd, "Hello, world!", 13);
        
        Result res_buffer;
        ssize_t bytes_read = read(fd, &res_buffer, sizeof(Result));
        
        if (bytes_read == sizeof(Result)) {
            printf("Структура успешно получена напрямую из ядра! [%d]\n", res_buffer.data.ret.int_v);
        }
        
        close(fd);
    }

    */

    printf("Free IRAM: %u bytes\n",
           heap_caps_get_free_size(MALLOC_CAP_EXEC));

    printf("Largest IRAM block: %u bytes\n",
           heap_caps_get_largest_free_block(MALLOC_CAP_EXEC));

    run_app_from_iram();
    
    while (true)
    {
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
    
    return 0;
}
