#include "nbgl_page.h"
#include "shared_context.h"
#include "ui_callbacks.h"
#include "ui_nbgl.h"
#include "sign_message.h"
#include "glyphs.h"
#include "nbgl_use_case.h"
#include "common_ui.h"
#include "ui_message_signing.h"
#include "ui_signing.h"

#define TEXT_REVIEW_EIP191 REVIEW(TEXT_MESSAGE)
#define TEXT_SIGN_EIP191   SIGN(TEXT_MESSAGE)

typedef enum {
    UI_191_ACTION_IDLE = 0,
    UI_191_ACTION_ADVANCE_IN_MESSAGE,
    UI_191_ACTION_GO_TO_SIGN
} e_ui_191_action;

static e_ui_191_action g_action;

static nbgl_contentTagValue_t pair;
static nbgl_contentTagValueList_t pairs_list;

static uint32_t g_display_buffer_idx;
static uint32_t g_rcv_buffer_idx;
static bool g_skipped;

static void ui_191_process_state(void);

static void reject_message(void) {
    io_seproxyhal_touch_signMessage_cancel();
}

static void sign_message(void) {
    io_seproxyhal_touch_signMessage_ok();
}

static void ui_191_finish_cb(bool confirm) {
    if (confirm) {
        nbgl_useCaseReviewStatus(STATUS_TYPE_MESSAGE_SIGNED, sign_message);
    } else {
        nbgl_useCaseReviewStatus(STATUS_TYPE_MESSAGE_REJECTED, reject_message);
    }
}

static void ui_191_skip_cb(void) {
    g_skipped = true;
    skip_rest_of_message();
}

static bool ui_191_update_display_buffer(void) {
    uint16_t len = 0;
    bool reached;

    g_stax_shared_buffer[g_display_buffer_idx] = '\0';
    strlcat(g_stax_shared_buffer + g_display_buffer_idx,
            strings.tmp.tmp + g_rcv_buffer_idx,
            sizeof(g_stax_shared_buffer) - g_display_buffer_idx);
    reached = nbgl_getTextMaxLenInNbLines(LARGE_MEDIUM_FONT,
                                          (char *) g_stax_shared_buffer,
                                          SCREEN_WIDTH - (2 * BORDER_MARGIN),
                                          NB_MAX_LINES_IN_REVIEW,
                                          &len,
                                          false);

    g_rcv_buffer_idx += (len - g_display_buffer_idx);
    g_display_buffer_idx = len;
    g_stax_shared_buffer[g_display_buffer_idx] = '\0';

    if (!reached) {
        g_rcv_buffer_idx = 0;
        question_switcher();
        return false;
    }
    g_display_buffer_idx = 0;
    return true;
}

static void ui_191_data_cb(bool more) {
    if (more) {
        ui_191_process_state();
    } else {
        ui_191_finish_cb(false);
    }
}

static void ui_191_show_message(void) {
    pair.value = g_stax_shared_buffer;
    pair.item = "Message";
    pairs_list.nbPairs = 1;
    pairs_list.pairs = &pair;
    pairs_list.smallCaseForValue = false;
    pairs_list.nbMaxLinesForValue = NB_MAX_LINES_IN_REVIEW;
    pairs_list.wrapping = false;
    nbgl_useCaseReviewStreamingContinueExt(&pairs_list, ui_191_data_cb, ui_191_skip_cb);
}

static void ui_191_process_state(void) {
    switch (g_action) {
        case UI_191_ACTION_IDLE:
            g_action = UI_191_ACTION_ADVANCE_IN_MESSAGE;
            __attribute__((fallthrough));
        case UI_191_ACTION_ADVANCE_IN_MESSAGE:
            if (ui_191_update_display_buffer()) {
                ui_191_show_message();
            }
            break;
        case UI_191_ACTION_GO_TO_SIGN:
            nbgl_useCaseReviewStreamingFinish(TEXT_SIGN_EIP191, ui_191_finish_cb);
            break;
    }
}

void ui_191_start(void) {
    g_action = UI_191_ACTION_IDLE;
    g_display_buffer_idx = 0;
    g_rcv_buffer_idx = 0;
    g_skipped = false;

    nbgl_useCaseReviewStreamingStart(TYPE_MESSAGE | SKIPPABLE_OPERATION,
                                     &C_Review_64px,
                                     TEXT_REVIEW_EIP191,
                                     NULL,
                                     ui_191_data_cb);
}

void ui_191_switch_to_message(void) {
    // Get following part of the message
    ui_191_process_state();
}

void ui_191_switch_to_sign(void) {
    g_action = UI_191_ACTION_GO_TO_SIGN;
    if (g_skipped) {
        nbgl_useCaseReviewStreamingFinish(TEXT_SIGN_EIP191, ui_191_finish_cb);
    } else if (g_display_buffer_idx > 0) {
        // still on an incomplete display buffer, show it before the last page
        ui_191_show_message();
    }
}

void ui_191_switch_to_question(void) {
    // No question mechanism on Stax: Always display the next message chunk.
    continue_displaying_message();
}
