
#include "unihiker_k10.h"
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <WiFiClientSecure.h>

UNIHIKER_K10 k10;
uint8_t      screen_dir=2;
Music        music;

const char* ssid = "YOURSSID";
const char* password = "YOURWIFIPASSWORD";

// ElevenLabs API configuration
const char* elevenlabs_api_key = "YOURAPIKEY";
const char* elevenlabs_stt_url = "";

enum ButtonEvent
{
    BTN_NONE,
    BTN_UP,
    BTN_DOWN,
    BTN_UP_DOUBLE,
    BTN_DOWN_DOUBLE
};

enum AppState
{
    STATE_MENU,          // Main menu
    STATE_TAG_SELECT,    // After recording, choose Ideas/Todo/Buy
    STATE_FILE_LIST,     // Show files for selected tag
    STATE_NOTE_DETAILS,  // Show transcript/details of a note
    STATE_UPLOADING,     // Upload WAV files to STT
    STATE_TRANSCRIPT     // Optional future use
};

AppState currentState = STATE_MENU;

enum MenuItem
{
    MENU_IDEAS,
    MENU_TODO,
    MENU_BUY,
    MENU_UPLOAD
};

int selectedMenu = MENU_IDEAS;
String transcriptText;
volatile ButtonEvent buttonEvent = BTN_NONE;
bool downWaitingForDouble = false;
uint32_t lastDownPress = 0;
bool upWaitingForDouble = false;
uint32_t lastUpPress = 0;

// Audio recording settings
#define WAV_FILE_NAME "recording"
#define SAMPLE_RATE 16000U
#define SAMPLE_BITS 16
#define WAV_HEADER_SIZE 44
#define VOLUME_GAIN 2

// Global variables
bool recording_active = false;
String last_transcription = "";
bool wifi_connected = false;
String current_recording_file = "";

String currentTag = "";

String fileList[50];

int fileCount = 0;

int selectedFile = 0;

String selectedFileName = "";

bool connectToWiFi() {
  Serial.println("Connecting to WiFi...");
  WiFi.disconnect();
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts < 40) {
    delay(500);
    Serial.print(".");
    attempts++;
  }

  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\nWiFi connected!");
    Serial.print("IP: ");
    Serial.println(WiFi.localIP());
    wifi_connected = true;
    return true;
  } else {
    Serial.println("\nWiFi connection failed");
    wifi_connected = false;
    return false;
  }
}

void setup() {
  Serial.begin(115200);
    k10.begin();
    connectToWiFi();
    k10.initScreen(screen_dir);
    k10.creatCanvas();
    k10.initSDFile();

     k10.canvas->canvasDrawImage(15, 0, "S:/photo1.png");
    k10.canvas->updateCanvas();
delay(1000);

    drawMenu();
    delay(1000);

    }

  void loop()
{
    //lv_timer_handler();
pollButtons();
processSingleClicks();

    switch(currentState)
{
    case STATE_MENU:
        handleMenu();
        break;

    case STATE_TAG_SELECT:
        handleTagSelect();
        break;

    case STATE_FILE_LIST:
        handleFileList();
        break;

    case STATE_NOTE_DETAILS:
        handleNoteDetails();
        break;
}

  //  delay(5);
}


void saveTranscriptFile(
    String txtName,
    String transcript)
{
    File f =
        SD.open(
            txtName,
            FILE_WRITE
        );

    if(!f)
    {
        Serial.println(
            "TXT create failed"
        );
        return;
    }

    f.print(transcript);

    f.close();

    Serial.print("Saved: ");
    Serial.println(txtName);
}

void processWavFile(String wavName)
{
    String txtName = wavName;

    txtName.replace(".wav", ".txt");

    String wavPath = wavName;

    if(!wavPath.startsWith("/"))
    {
        wavPath = "/" + wavPath;
    }

    if(!txtName.startsWith("/"))
    {
        txtName = "/" + txtName;
    }

    // if(SD.exists(txtName))
    // {
    //     Serial.print("Skipping: ");
    //     Serial.println(txtName);
    //     return;
    // }

    Serial.print("Uploading: ");
    Serial.println(wavPath);

    String transcript =
        send_to_elevenlabs_stt(wavPath);

    saveTranscriptFile(
        txtName,
        transcript
    );
}

void uploadAllFiles()
{
    int total =
        countWavFiles();

    int current = 0;

    File root =
        SD.open("/");

    while(true)
    {
        File file =
            root.openNextFile();

        if(!file)
            break;

        String wavName =
            file.name();

        if(wavName.endsWith(".wav"))
        {
            current++;

            showUploadingScreen(
                wavName,
                current,
                total
            );

            processWavFile(
                wavName
            );
        }

        file.close();
    }

    root.close();

    showUploadDoneScreen(
        total
    );

    delay(2000);

    currentState =
        STATE_MENU;

    drawMenu();
}

bool lastUpState = false;
bool lastDownState = false;

void pollButtons()
{
    bool upState = k10.buttonB->isPressed();
    bool downState = k10.buttonA->isPressed();

    if(upState && !lastUpState)
    {
        onUpPressed();
    }

    if(downState && !lastDownState)
    {
        onDownPressed();
    }

    lastUpState = upState;
    lastDownState = downState;
}

  

void showUploadingScreen(
    String fileName,
    int current,
    int total)
{
    lv_obj_clean(
        lv_scr_act()
    );

    lv_obj_t *title =
        lv_label_create(
            lv_scr_act()
        );

    lv_label_set_text(
        title,
        "Uploading..."
    );

    lv_obj_align(
        title,
        LV_ALIGN_TOP_MID,
        0,
        20
    );

    String progress =
        String(current) +
        " / " +
        String(total);

    lv_obj_t *label1 =
        lv_label_create(
            lv_scr_act()
        );

    lv_label_set_text(
        label1,
        progress.c_str()
    );

    lv_obj_align(
        label1,
        LV_ALIGN_CENTER,
        0,
        -20
    );

    lv_obj_t *label2 =
        lv_label_create(
            lv_scr_act()
        );

    lv_label_set_text(
        label2,
        fileName.c_str()
    );

    lv_obj_align(
        label2,
        LV_ALIGN_CENTER,
        0,
        20
    );

    lv_timer_handler();
}

void showUploadDoneScreen(
    int totalFiles)
{
    lv_obj_clean(
        lv_scr_act()
    );

    lv_obj_t *title =
        lv_label_create(
            lv_scr_act()
        );

    lv_label_set_text(
        title,
        "Upload Complete"
    );

    lv_obj_align(
        title,
        LV_ALIGN_CENTER,
        0,
        -20
    );

    String msg =
        String(totalFiles) +
        " files processed";

    lv_obj_t *label =
        lv_label_create(
            lv_scr_act()
        );

    lv_label_set_text(
        label,
        msg.c_str()
    );

    lv_obj_align(
        label,
        LV_ALIGN_CENTER,
        0,
        20
    );

    lv_timer_handler();
}

int countWavFiles()
{
    int count = 0;

    File root = SD.open("/");

    while(true)
    {
        File file =
            root.openNextFile();

        if(!file)
            break;

        String name =
            file.name();

        if(name.endsWith(".wav"))
        {
            count++;
        }

        file.close();
    }

    root.close();

    return count;
}


void handleNoteDetails()
{
    if(buttonEvent == BTN_UP_DOUBLE)
    {
      //  music.stopAudio();

        currentState = STATE_MENU;

        selectedMenu = 0;

        drawMenu();

        buttonEvent = BTN_NONE;
    }
}

String readTextFile(String fileName)
{
    if(!fileName.startsWith("/"))
    {
        fileName = "/" + fileName;
    }

    File f = SD.open(fileName);

    if(!f)
    {
        return "Transcript not found";
    }

    String content = "";

    while(f.available())
    {
        content += (char)f.read();
    }

    f.close();

    return content;
}

void drawNoteDetails()
{
    String txtFile =
        selectedFileName;

    txtFile.replace(
        ".wav",
        ".txt"
    );

    String transcript =
        readTextFile(
            txtFile
        );

    lv_obj_clean(
        lv_scr_act()
    );

    lv_obj_t *title =
        lv_label_create(
            lv_scr_act()
        );

    lv_label_set_text(
        title,
        selectedFileName.c_str()
    );

    lv_obj_align(
        title,
        LV_ALIGN_TOP_MID,
        0,
        10
    );

    lv_obj_t *body =
        lv_label_create(
            lv_scr_act()
        );

    lv_obj_set_width(
        body,
        220
    );

    lv_label_set_long_mode(
        body,
        LV_LABEL_LONG_WRAP
    );

    lv_label_set_text(
        body,
        transcript.c_str()
    );

    lv_obj_align(
        body,
        LV_ALIGN_TOP_LEFT,
        10,
        50
    );

    lv_timer_handler();
String wavPath =
    "S:/" +
    selectedFileName;

    Serial.print("Playing: ");
    Serial.println(wavPath);

    music.playTFCardAudio(
        wavPath.c_str()
    );
}

void handleFileList()
{
    if(buttonEvent == BTN_UP)
    {
        selectedFile--;

        if(selectedFile < 0)
        {
            selectedFile = fileCount - 1;
        }

        drawFileList();

        buttonEvent = BTN_NONE;
    }

    if(buttonEvent == BTN_DOWN)
    {
        selectedFile++;

        if(selectedFile >= fileCount)
        {
            selectedFile = 0;
        }

        drawFileList();

        buttonEvent = BTN_NONE;
    }

    if(buttonEvent == BTN_DOWN_DOUBLE)
    {
        selectedFileName =
            fileList[selectedFile];

        currentState =
            STATE_NOTE_DETAILS;

        drawNoteDetails();

        buttonEvent = BTN_NONE;
    }

    if(buttonEvent == BTN_UP_DOUBLE)
    {
        currentState =
            STATE_MENU;

        selectedMenu = 0;

        drawMenu();

        buttonEvent = BTN_NONE;
    }
}

void handleTagSelect()
{
    if(buttonEvent == BTN_UP)
    {
        selectedMenu--;

        if(selectedMenu < 0)
            selectedMenu = 2;

        drawMenu();

        buttonEvent = BTN_NONE;
    }

    if(buttonEvent == BTN_DOWN)
    {
        selectedMenu++;

        if(selectedMenu > 2)
            selectedMenu = 0;

        drawMenu();

        buttonEvent = BTN_NONE;
    }

    if(buttonEvent == BTN_DOWN_DOUBLE)
    {
        saveTaggedRecording();

        buttonEvent = BTN_NONE;
    }

    if(buttonEvent == BTN_UP_DOUBLE)
    {
        currentState = STATE_MENU;

        drawMenu();

        buttonEvent = BTN_NONE;
    }
}

void handleMenu()
{
    if(buttonEvent == BTN_UP)
    {
        selectedMenu--;

        int maxItems =
            (currentState == STATE_TAG_SELECT)
            ? 3
            : 4;

        if(selectedMenu < 0)
            selectedMenu = maxItems - 1;

        drawMenu();

        buttonEvent = BTN_NONE;
    }

    if(buttonEvent == BTN_DOWN)
    {
        int maxItems =
            (currentState == STATE_TAG_SELECT)
            ? 3
            : 4;

        selectedMenu++;

        if(selectedMenu >= maxItems)
            selectedMenu = 0;

        drawMenu();

        buttonEvent = BTN_NONE;
    }

    if(buttonEvent == BTN_DOWN_DOUBLE)
    {
        if(selectedMenu == MENU_UPLOAD)
        {
            uploadAllFiles();
        }
        else
        {
            showTagFiles();
        }

        buttonEvent = BTN_NONE;
    }

    if(buttonEvent == BTN_UP_DOUBLE)
    {
        startRecording();

        buttonEvent = BTN_NONE;
    }
}

void showTagFiles()
{
    fileCount = 0;

    switch(selectedMenu)
    {
        case MENU_IDEAS:
            currentTag = "idea_";
            break;

        case MENU_TODO:
            currentTag = "todo_";
            break;

        case MENU_BUY:
            currentTag = "buy_";
            break;

        default:
            return;
    }

    File root = SD.open("/");

    if(!root)
    {
        Serial.println("Root open failed");
        return;
    }

    while(true)
    {
        File file = root.openNextFile();

        if(!file)
            break;

        String name = file.name();

        Serial.println(name);

        if(name.startsWith(currentTag) &&
           name.endsWith(".wav"))
        {
            fileList[fileCount] = name;

            fileCount++;

            if(fileCount >= 50)
                break;
        }

        file.close();
    }

    root.close();

    selectedFile = 0;

    currentState = STATE_FILE_LIST;

    drawFileList();
}
void drawFileList()
{
    lv_obj_clean(lv_scr_act());

    lv_obj_t *title =
        lv_label_create(lv_scr_act());

    lv_label_set_text(
        title,
        currentTag.c_str()
    );

    lv_obj_align(
        title,
        LV_ALIGN_TOP_MID,
        0,
        15
    );

    if(fileCount == 0)
    {
        lv_obj_t *label =
            lv_label_create(lv_scr_act());

        lv_label_set_text(
            label,
            "No recordings"
        );

        lv_obj_center(label);

        lv_timer_handler();

        return;
    }

    for(int i = 0; i < fileCount; i++)
    {
        lv_obj_t *label =
            lv_label_create(lv_scr_act());

        String text =
            (i == selectedFile)
            ? "> "
            : "  ";

        text += fileList[i];

        lv_label_set_text(
            label,
            text.c_str()
        );

        lv_obj_align(
            label,
            LV_ALIGN_TOP_LEFT,
            10,
            50 + (i * 25)
        );
    }

    lv_timer_handler();
}

void saveTaggedRecording()
{
    String newName;

    switch(selectedMenu)
    {
        case MENU_IDEAS:
            newName = "/idea_1.wav";
            break;

        case MENU_TODO:
            newName = "/todo_1.wav";
            break;

        case MENU_BUY:
            newName = "/buy_1.wav";
            break;
    }

    if(SD.rename("/temp.wav", newName.c_str()))
    {
        Serial.println("Saved");
    }
    else
    {
        Serial.println("Save Failed");
    }

    showSavedScreen();

    delay(1500);

    currentState = STATE_MENU;

    selectedMenu = 0;

    drawMenu();
}

void startRecording()
{
    showRecordingScreen();

    music.recordSaveToTFCard(
        "S:/temp.wav",
        5
    );

    currentState = STATE_TAG_SELECT;

    selectedMenu = 0;

    drawMenu();
}

void handleUploading()
{
    showUploadingScreen();

    transcriptText =
        send_to_elevenlabs_stt(
            "/temp.wav"
        );

    currentState =
        STATE_TRANSCRIPT;
}

void saveTranscript()
{
    Serial.println("Saving transcript...");
}

void handleTranscript()
{
    showTranscript(
        transcriptText
    );

    if(buttonEvent ==
       BTN_DOWN_DOUBLE)
    {
        saveTranscript();

        currentState =
            STATE_MENU;

        drawMenu();

        buttonEvent =
            BTN_NONE;
    }
}



void drawMenu()
{
    lv_obj_clean(lv_scr_act());

    static const char* items[] =
    {
        "Ideas",
        "Todo",
        "Buy",
        "Upload"
    };

    lv_obj_t *title = lv_label_create(lv_scr_act());

 if(currentState == STATE_TAG_SELECT)
{
    lv_label_set_text(title, "Select Tag");
}
else
{
    lv_label_set_text(title, "QuickNote");
}

    lv_obj_align(title, LV_ALIGN_TOP_MID, 0, 20);
int itemCount =
    (currentState == STATE_TAG_SELECT)
    ? 3
    : 4;

for(int i=0;i<itemCount;i++)
    {
        lv_obj_t *label = lv_label_create(lv_scr_act());

        String text;

        if(i == selectedMenu)
            text = "> " + String(items[i]);
        else
            text = "  " + String(items[i]);

        lv_label_set_text(label, text.c_str());

        lv_obj_align(label,
                     LV_ALIGN_TOP_LEFT,
                     40,
                     80 + (i * 35));
    }

    lv_timer_handler();
}

void showRecordingScreen()
{
    lv_obj_clean(lv_scr_act());

    lv_obj_t *icon = lv_label_create(lv_scr_act());

    lv_label_set_text(icon, LV_SYMBOL_AUDIO);

    lv_obj_align(icon,
                 LV_ALIGN_CENTER,
                 0,
                 -40);

    lv_obj_t *label = lv_label_create(lv_scr_act());

    lv_label_set_text(label,
                      "Recording...");

    lv_obj_align(label,
                 LV_ALIGN_CENTER,
                 0,
                 0);

    lv_obj_t *hint = lv_label_create(lv_scr_act());

    lv_label_set_text(hint,
                      "Press UP to stop");

    lv_obj_align(hint,
                 LV_ALIGN_BOTTOM_MID,
                 0,
                 -30);

    lv_timer_handler();
}

void showUploadingScreen()
{
    lv_obj_clean(lv_scr_act());

    lv_obj_t *label = lv_label_create(lv_scr_act());

    lv_label_set_text(label,
                      "Uploading...");

    lv_obj_center(label);

    lv_timer_handler();
}

void showTranscript(String text)
{
    lv_obj_clean(lv_scr_act());

    lv_obj_t *title = lv_label_create(lv_scr_act());

    lv_label_set_text(title,
                      "Transcript");

    lv_obj_align(title,
                 LV_ALIGN_TOP_MID,
                 0,
                 15);

    lv_obj_t *body = lv_label_create(lv_scr_act());

    lv_label_set_long_mode(body,
                           LV_LABEL_LONG_WRAP);

    lv_obj_set_width(body, 220);

    lv_label_set_text(body,
                      text.c_str());

    lv_obj_align(body,
                 LV_ALIGN_TOP_LEFT,
                 10,
                 50);

    lv_timer_handler();
}

void showSavedScreen()
{
    lv_obj_clean(lv_scr_act());

    lv_obj_t *label = lv_label_create(lv_scr_act());

    lv_label_set_text(label,
                      "Saved");

    lv_obj_center(label);

    lv_timer_handler();
}

void openCategory(String name)
{
    lv_obj_clean(lv_scr_act());

    lv_obj_t *title = lv_label_create(lv_scr_act());

    lv_label_set_text(title,
                      name.c_str());

    lv_obj_align(title,
                 LV_ALIGN_TOP_MID,
                 0,
                 15);

    lv_obj_t *label = lv_label_create(lv_scr_act());

    lv_label_set_text(label,
                      "No notes");

    lv_obj_center(label);

    lv_timer_handler();
}

void onUpPressed()
{
    uint32_t now = millis();


    if(upWaitingForDouble &&
       (now - lastUpPress < 300))
    {
        buttonEvent = BTN_UP_DOUBLE;

        upWaitingForDouble = false;

        Serial.println("UP DOUBLE");
    }
    else
    {
        upWaitingForDouble = true;

        lastUpPress = now;
    }
}

void onDownPressed()
{
    uint32_t now = millis();

    if(downWaitingForDouble &&
       (now - lastDownPress < 300))
    {
        buttonEvent = BTN_DOWN_DOUBLE;

        downWaitingForDouble = false;

        Serial.println("DOWN DOUBLE");
    }
    else
    {
        downWaitingForDouble = true;

        lastDownPress = now;
    }
}

void processSingleClicks()
{
    if(buttonEvent == BTN_NONE &&
       upWaitingForDouble &&
       millis() - lastUpPress > 300)
    {
        buttonEvent = BTN_UP;

        upWaitingForDouble = false;

        Serial.println("UP SINGLE");
    }

    if(buttonEvent == BTN_NONE &&
       downWaitingForDouble &&
       millis() - lastDownPress > 300)
    {
        buttonEvent = BTN_DOWN;

        downWaitingForDouble = false;

        Serial.println("DOWN SINGLE");
    }
}

String send_to_elevenlabs_stt(String filename)
{
    if (!wifi_connected || WiFi.status() != WL_CONNECTED)
    {
        Serial.println("WiFi not connected");
        return "";
    }

    File file = SD.open(filename.c_str());

    if (!file)
    {
        Serial.println("Failed to open file");
        return "";
    }

    WiFiClientSecure client;
    client.setInsecure();

    Serial.println("Connecting to ElevenLabs...");

    if (!client.connect("api.elevenlabs.io", 443))
    {
        Serial.println("Connection failed");
        file.close();
        return "";
    }

    String boundary = "----K10Boundary123456";

    String bodyStart =
        "--" + boundary + "\r\n"
        "Content-Disposition: form-data; name=\"model_id\"\r\n\r\n"
        "scribe_v1\r\n"
        "--" + boundary + "\r\n"
        "Content-Disposition: form-data; name=\"file\"; filename=\"audio.wav\"\r\n"
        "Content-Type: audio/wav\r\n\r\n";

    String bodyEnd =
        "\r\n--" + boundary + "--\r\n";

    size_t contentLength =
        bodyStart.length() +
        file.size() +
        bodyEnd.length();

    Serial.printf("Audio size: %u\n", file.size());
    Serial.printf("Content length: %u\n", contentLength);

    client.printf(
        "POST /v1/speech-to-text HTTP/1.1\r\n"
        "Host: api.elevenlabs.io\r\n"
        "xi-api-key: %s\r\n"
        "Content-Type: multipart/form-data; boundary=%s\r\n"
        "Content-Length: %u\r\n"
        "Connection: close\r\n"
        "\r\n",
        elevenlabs_api_key,
        boundary.c_str(),
        contentLength
    );

    client.print(bodyStart);

    uint8_t buffer[1024];

    while (file.available())
    {
        size_t n = file.read(buffer, sizeof(buffer));

        if (n > 0)
        {
            client.write(buffer, n);
        }
    }

    file.close();

    client.print(bodyEnd);

    Serial.println("Upload finished");

   String response = "";

while(client.connected() || client.available())
{
    while(client.available())
    {
        char c = client.read();
        response += c;
    }

    delay(10);
}

Serial.println(response);

    unsigned long timeout = millis();

    while (client.connected() && millis() - timeout < 30000)
    {
        while (client.available())
        {
            char c = client.read();
            response += c;
            timeout = millis();
        }
    }

    client.stop();

    Serial.println("========== RAW RESPONSE ==========");
    Serial.println(response);
    Serial.println("==================================");

    int jsonStart = response.indexOf('{');

    if (jsonStart < 0)
    {
        Serial.println("No JSON found");
        return "";
    }

    String json =
        response.substring(jsonStart);

    DynamicJsonDocument doc(8192);

    DeserializationError err =
        deserializeJson(doc, json);

    if (err)
    {
        Serial.println("JSON parse failed");
        Serial.println(err.c_str());
        return "";
    }

    if (doc.containsKey("text"))
    {
        String text =
            doc["text"].as<String>();

        Serial.println("Transcription:");
        Serial.println(text);

        return text;
    }

    Serial.println("No text field");

    serializeJsonPretty(doc, Serial);
    Serial.println();

    return "";
}


