#include "TZ_Vendor_debug_tl.h"
#include "Vendor_Interface.h"
#include "tl_tui_bc_error_msg.h"

#include "TuiButton.h"
#include "TuiTextBox.h"
#include "TuiBackupScreenController.h"
#include "TuiScreenResource.h"
#include "TuiLayout.h"
#include "TuiImageView.h"

#define MAX_MNEMONIC_WORD_COUNT			24
#define MAX_MNEMONIC_WORD_LENGTH		8
#define MAX_MNEMONIC_ARRAY_SIZE			240
#define QUIZ_WORD_COUNT					3
#define MNEMONIC_ROW_COUNT              4
#define MNEMONIC_PHRASE_NUMBER_LENGTH   3

uint8_t listNum[MAX_MNEMONIC_WORD_COUNT][3 + 1] = { '\0', };
uint8_t mnemonicList[MAX_MNEMONIC_WORD_COUNT][MAX_MNEMONIC_WORD_LENGTH + 1] = { '\0', };
uint8_t mnemonicPhraseNum[MNEMONIC_PHRASE_NUMBER_LENGTH + 1] = {'\0', };

Node gBackupScreenControlNode[MAX_CONTROL];
Node gBackupScreenQuizControlNode[MAX_CONTROL];
uint32_t gBackupQuizOrderArray[QUIZ_WORD_COUNT] = { 0, };

ControlGroup gGroupBackupList;
ControlGroup gGroupQuizTextEdit;
ControlGroup gGroupQuizEnterButton;
ControlGroup gGroupQuizTextEditImage;

static uint8_t emptyString[1] = { '\0' };

uint32_t gCurrentMnemonicPhrase;
uint32_t gMnemonicTotalCount;
uint32_t gMnemonicPhraseNodeStartIdx;

bool gCheckboxState;

uint32_t initBackupScreenController() {
	initLayout();
	initTextBuffer();

	return TIMA_SUCCESS;
}

void deleteAllBackupScreenQuizControl() {
	for (uint32_t i = 0; i < MAX_CONTROL; ++i) {
		clearNode(&gBackupScreenQuizControlNode[i]);
	}
}

Node* getBackupScreenControlNode(ScreenState state) {
	if (state == BACKUP_SCREEN_QUIZ_STATE) {
		deleteAllBackupScreenQuizControl();
		return gBackupScreenQuizControlNode;
	} else {
		return gBackupScreenControlNode;
	}
}

uint32_t* getBackupQuizOrderArray() {
	return gBackupQuizOrderArray;
}

void parseMnemonicData(uint8_t* mnemonicData) {
	uint32_t index = 0;
	uint32_t i = 0, j = 0;

	for (uint8_t idx = 0; idx < MAX_MNEMONIC_WORD_COUNT; idx++) {
	    memset(mnemonicList[idx], 0, MAX_MNEMONIC_WORD_LENGTH + 1);
	}

	do {
		if (mnemonicData[i] == ' ' || mnemonicData[i] == '\0') {
			memcpy(mnemonicList[index++], mnemonicData + j, i - j);
			DBG_LOG("mnemonicList :  %s", mnemonicList[index - 1]);
			if (mnemonicData[i] == '\0') {
				break;
			}
			j = i + 1;
		}
		i++;
	} while (i < MAX_MNEMONIC_ARRAY_SIZE);

	gMnemonicTotalCount = index;
}

void initMnemonicPhrase() {
    uint32_t startIdx = gCurrentMnemonicPhrase * MNEMONIC_ROW_COUNT;
    uint32_t endIdx = startIdx + MNEMONIC_ROW_COUNT;

    Control control;
    Location loc;
    uint32_t controlId = 1;

    for (uint8_t i = 0; i < MAX_CONTROL; i++) {
        if (gBackupScreenControlNode[i].control.kindOfControl == NONE_CONTROL_TYPE) {
            gMnemonicPhraseNodeStartIdx = i;
            break;
        }
    }

    gGroupBackupList.startId = controlId;
    gGroupBackupList.groupSize = gMnemonicTotalCount * 2;

    TextInfo textInfo;
    uint8_t number[4] = { '\0', };
    uint32_t numSize;

    for (uint32_t i = startIdx; i < endIdx; i++) {
        loc.x1 = BACKUP_MNEMONIC_LIST_SIDE_MARGIN;
        loc.y1 = BACKUP_MNEMONIC_LIST_TOP_MARGIN + (BACKUP_MNEMONIC_LIST_TEXTBOX_HEIGHT + BACKUP_MNEMONIC_LIST_TEXTBOX_LINE_DISTANCE) * (i % MNEMONIC_ROW_COUNT);
        if (i + 1 >= 10) {
            number[0] = (uint8_t) ('0' + (i + 1) / 10);
            number[1] = (uint8_t) ('0' + (i + 1) % 10);
            number[2] = '.';
            numSize = 3;
        } else {
            number[0] = (uint8_t) ('0' + (i + 1) % 10);
            number[1] = '.';
            numSize = 2;
        }
        memcpy(listNum[i], number, numSize);
        textInfo.text = listNum[i];
        textInfo.font = getScreenFontType(ID_FONT_TYPE_BACKUP_MNEMONIC_LIST);
        initTextBox(&control, controlId++, loc, BACKUP_MNEMONIC_LIST_NUMBER_WIDTH, BACKUP_MNEMONIC_LIST_TEXTBOX_HEIGHT, NULL, 0, NULL, 0, textInfo, RIGHT_CONTENT_ALIGN, VERTICAL_CENTER_CONTENT_ALIGN);
        addTextViewBox(&control, executeTextViewBox);

        DBG_LOG("loc : %d, %d", loc.x1, loc.y1);
        DBG_LOG("mnemonicList : %s", mnemonicList[i]);
        loc.x1 += (BACKUP_MNEMONIC_LIST_NUMBER_WIDTH + BACKUP_MNEMONIC_LIST_NUMBER_DISTANCE);
        textInfo.text = mnemonicList[i];
        textInfo.font = getScreenFontType(ID_FONT_TYPE_BACKUP_MNEMONIC_LIST);
        initTextBox(&control, controlId++, loc, BACKUP_MNEMONIC_LIST_TEXTBOX_WIDTH, BACKUP_MNEMONIC_LIST_TEXTBOX_HEIGHT, NULL, 0, NULL, 0, textInfo, LEFT_CONTENT_ALIGN, VERTICAL_CENTER_CONTENT_ALIGN);
        addTextViewBox(&control, executeTextViewBox);
    }
}

void initMnemonicPhraseNumber() {
    Control control;
    TextInfo textInfo;
    uint32_t controlId = ID_FONT_TYPE_BACKUP_MNEMONIC_PHRASE_NUMBER;
    Location loc;

    mnemonicPhraseNum[0] = (uint8_t) ('0' + gCurrentMnemonicPhrase + 1);
    mnemonicPhraseNum[1] = '/';
    mnemonicPhraseNum[2] = (uint8_t) ('0' + gMnemonicTotalCount / MNEMONIC_ROW_COUNT);

    textInfo.text = mnemonicPhraseNum;
    textInfo.font = getScreenFontType(ID_FONT_TYPE_BACKUP_MNEMONIC_PHRASE_NUMBER);

    loc.x1 = (SCREEN_WIDTH - BACKUP_MNEMONIC_PHRASE_NUMBER_TEXTBOX_WIDTH) / 2;
    loc.y1 = BACKUP_MNEMONIC_PHRASE_NUMBER_TEXTBOX_TOP_MARGIN;

    initTextBox(&control, controlId, loc, BACKUP_MNEMONIC_PHRASE_NUMBER_TEXTBOX_WIDTH, BACKUP_MNEMONIC_PHRASE_NUMBER_TEXTBOX_HEIGHT, NULL, 0, NULL, 0, textInfo, CENTER_CONTENT_ALIGN, VERTICAL_CENTER_CONTENT_ALIGN);
    addTextViewBox(&control, executeTextViewBox);
}

void drawBackupScreen() {
    uint32_t startIdx = gCurrentMnemonicPhrase * MNEMONIC_ROW_COUNT;
    uint32_t endIdx = startIdx + MNEMONIC_ROW_COUNT;

    TextInfo textInfo;
    uint8_t number[4] = { '\0', };
    uint32_t numSize;
    uint32_t mnemonicPhraseNodeNumber = gMnemonicPhraseNodeStartIdx;

    for (uint32_t i = startIdx; i < endIdx; i++) {
        if (i + 1 >= 10) {
            number[0] = (uint8_t) ('0' + (i + 1) / 10);
            number[1] = (uint8_t) ('0' + (i + 1) % 10);
            number[2] = '.';
            numSize = 3;
        } else {
            number[0] = (uint8_t) ('0' + (i + 1) % 10);
            number[1] = '.';
            numSize = 2;
        }
        memset(gBackupScreenControlNode[mnemonicPhraseNodeNumber].control.textInfo.text, '\0', 3);
        memcpy(gBackupScreenControlNode[mnemonicPhraseNodeNumber].control.textInfo.text, number, numSize);
        drawTextBox(&gBackupScreenControlNode[mnemonicPhraseNodeNumber++].control);

        DBG_LOG("mnemonicList : %s", mnemonicList[i]);
        textInfo.text = mnemonicList[i];
        textInfo.font = getScreenFontType(ID_FONT_TYPE_BACKUP_MNEMONIC_LIST);
        gBackupScreenControlNode[mnemonicPhraseNodeNumber].control.textInfo.text = mnemonicList[i];
        drawTextBox(&gBackupScreenControlNode[mnemonicPhraseNodeNumber++].control);
    }
}

void drawMnemonicPhraseNumber() {
    mnemonicPhraseNum[0] = (uint8_t) ('0' + gCurrentMnemonicPhrase + 1);
    mnemonicPhraseNum[1] = '/';
    mnemonicPhraseNum[2] = (uint8_t) ('0' + gMnemonicTotalCount / MNEMONIC_ROW_COUNT);

    gBackupScreenControlNode[gMnemonicPhraseNodeStartIdx + 8].control.textInfo.text = mnemonicPhraseNum;
    drawTextBox(&gBackupScreenControlNode[gMnemonicPhraseNodeStartIdx + 8].control);
}

void initBackupScreen(uint8_t* mnemonicData) {
    gCurrentMnemonicPhrase = 0;
    gCheckboxState = false;
	parseMnemonicData(mnemonicData);
	initMnemonicPhrase();
	initMnemonicPhraseNumber();
	setEnableButtonNextMnemonicPhrase();
    setInvisibleCheckboxAndNextButton();
}

void clearMnemonicPhrase() {
    Node* node = pickingControlById(ID_CONTROL_IMAGE_VIEW_MNEMONIC_PHRASE_SCREENING);
    if (node == NULL) {
        return;
    }
    drawImageView(&node->control);
}

void clearMnemonicPhraseNumber() {
    Node* node = pickingControlById(ID_CONTROL_IMAGE_VIEW_MNEMONIC_PHRASE_NUMBER_SCREENING);
    if (node == NULL) {
        return;
    }
    drawImageView(&node->control);
}

void setEnableButtonPreviousMnemonicPhrase() {
	Node* node = pickingControlById(ID_CONTROL_BUTTON_MNEMONIC_PHRASE_PREVIOUS);
	if (node == NULL || node->control.state == ENABLE_CONTROL_STATE) {
		return;
	}
	node->control.state = ENABLE_CONTROL_STATE;
	drawButton(&node->control);
}

void setInvisibleButtonPreviousMnemonicPhrase() {
	Node* node = pickingControlById(ID_CONTROL_BUTTON_MNEMONIC_PHRASE_PREVIOUS);
	if (node == NULL || node->control.state == DISABLE_CONTROL_STATE) {
		return;
	}
	node->control.state = DISABLE_CONTROL_STATE;
	drawButton(&node->control);
}

void setEnableButtonNextMnemonicPhrase() {
	Node* node = pickingControlById(ID_CONTROL_BUTTON_MNEMONIC_PHRASE_NEXT);
	if (node == NULL || node->control.state == ENABLE_CONTROL_STATE) {
		return;
	}
	node->control.state = ENABLE_CONTROL_STATE;
	drawButton(&node->control);
}

void setInvisibleButtonNextMnemonicPhrase() {
	Node* node = pickingControlById(ID_CONTROL_BUTTON_MNEMONIC_PHRASE_NEXT);
	if (node == NULL || node->control.state == DISABLE_CONTROL_STATE) {
		return;
	}
	node->control.state = DISABLE_CONTROL_STATE;
	drawButton(&node->control);
}

uint32_t getMnemonicPhraseSize() {
	return (gMnemonicTotalCount / MNEMONIC_ROW_COUNT) - 1;
}

void showNextButton() {
    Node* node = pickingControlById(ID_CONTROL_BUTTON_BACKUP_OK);
    if (node == NULL) {
        return;
    }
    node->control.state = DISABLE_CONTROL_STATE;
    drawButton(&node->control);
}

void showWriteItDownButton() {
	Node* node = pickingControlById(ID_CONTROL_IMAGE_WRITE_IT_DOWN);
	if (node == NULL) {
		return;
	}
	node->control.state = ENABLE_CONTROL_STATE;
	drawButton(&node->control);
}

void initCheckboxAndNextButton() {
    gCheckboxState = false;
    if (gCurrentMnemonicPhrase == getMnemonicPhraseSize()) {
        setCheckboxStates(gCheckboxState);
        showWriteItDownButton();
        showNextButton();
    }
}

void setInvisibleCheckboxAndNextButton() {
	Node* nodeScreening = pickingControlById(ID_CONTROL_IMAGE_CHECKBOX_SCREENING);
	Node* nodeCheckboxOff = pickingControlById(ID_CONTROL_IMAGE_CHECKBOX_OFF);
	Node* nodeCheckboxOn = pickingControlById(ID_CONTROL_IMAGE_CHECKBOX_ON);
	Node* nodeWriteItDown = pickingControlById(ID_CONTROL_IMAGE_WRITE_IT_DOWN);
	Node* nodeNext = pickingControlById(ID_CONTROL_BUTTON_BACKUP_OK);

	if (nodeScreening == NULL || nodeCheckboxOff == NULL || nodeCheckboxOn == NULL
		|| nodeNext == NULL || nodeWriteItDown == NULL) {
		return;
	}

	nodeScreening->control.state = ENABLE_CONTROL_STATE;
	nodeCheckboxOff->control.state = INVISIBLE_CONTROL_STATE;
	nodeCheckboxOn->control.state = INVISIBLE_CONTROL_STATE;
	nodeWriteItDown->control.state = DISABLE_CONTROL_STATE;
	nodeNext->control.state = DISABLE_CONTROL_STATE;

	if (gCurrentMnemonicPhrase != getMnemonicPhraseSize()) {
        drawImageView(&nodeScreening->control);
	}
}

void setDisableScreeningCheckboxAndNextButton() {
    Node* nodeScreening = pickingControlById(ID_CONTROL_IMAGE_CHECKBOX_SCREENING);

    if (nodeScreening == NULL || nodeScreening->control.state == DISABLE_CONTROL_STATE) {
        return;
    }

    nodeScreening->control.state = DISABLE_CONTROL_STATE;
}

void setCurrentMnemonicPhraseNext() {
	if (gCurrentMnemonicPhrase < getMnemonicPhraseSize()) {
		gCurrentMnemonicPhrase++;
	}

	if (gCurrentMnemonicPhrase == getMnemonicPhraseSize()) {
        setDisableScreeningCheckboxAndNextButton();
        setInvisibleButtonNextMnemonicPhrase();
        initCheckboxAndNextButton();
	} else if (gCurrentMnemonicPhrase == 1) {
		setEnableButtonPreviousMnemonicPhrase();
	}

    initTextBuffer();
    clearMnemonicPhrase();
    clearMnemonicPhraseNumber();
    drawBackupScreen();
    drawMnemonicPhraseNumber();
}

void setCurrentMnemonicPhrasePrevious() {
	if (gCurrentMnemonicPhrase > 0) {
		gCurrentMnemonicPhrase--;
	}

    if (gCurrentMnemonicPhrase == 0) {
        setInvisibleButtonPreviousMnemonicPhrase();
    } else if (gCurrentMnemonicPhrase == getMnemonicPhraseSize() - 1) {
        setEnableButtonNextMnemonicPhrase();
        setDisableNextButton();
        setInvisibleCheckboxAndNextButton();
    }

    initTextBuffer();
    clearMnemonicPhrase();
    clearMnemonicPhraseNumber();
    drawBackupScreen();
    drawMnemonicPhraseNumber();
}

ResponseControl executeButtonMnemonicPhrasePrevious(Control *control) {
	ResponseControl rc;
	initResponseControl(&rc);

	switch (control->state) {
		case RELEASED_CONTROL_STATE:
            drawButton(control);
            setCurrentMnemonicPhrasePrevious();
            break;
		case PRESSED_CONTROL_STATE:
			drawButton(control);
			break;
		default:
			break;
	}

	return rc;
}

ResponseControl executeButtonMnemonicPhraseNext(Control *control) {
	ResponseControl rc;
	initResponseControl(&rc);

	switch (control->state) {
		case RELEASED_CONTROL_STATE:
            drawButton(control);
            setCurrentMnemonicPhraseNext();
			break;
		case PRESSED_CONTROL_STATE:
			drawButton(control);
			break;
		default:
			break;
	}

	return rc;
}

void setEnableNextButton() {
	Node* node = pickingControlById(ID_CONTROL_BUTTON_BACKUP_OK);
	if (node == NULL || node->control.state == ENABLE_CONTROL_STATE) {
		return;
	}
	node->control.state = ENABLE_CONTROL_STATE;
	drawButton(&node->control);
}

void setDisableNextButton() {
	Node* node = pickingControlById(ID_CONTROL_BUTTON_BACKUP_OK);
	if (node == NULL || node->control.state == DISABLE_CONTROL_STATE) {
		return;
	}
	node->control.state = DISABLE_CONTROL_STATE;
	drawButton(&node->control);
}

void setCheckboxStates(bool bCheckboxOn) {
	Node *nodeCheckboxOff = pickingControlById(ID_CONTROL_IMAGE_CHECKBOX_OFF);
	Node *nodeCheckboxOn = pickingControlById(ID_CONTROL_IMAGE_CHECKBOX_ON);

	if (nodeCheckboxOff == NULL || nodeCheckboxOff->control.state == DISABLE_CONTROL_STATE
		|| nodeCheckboxOn == NULL || nodeCheckboxOn->control.state == DISABLE_CONTROL_STATE) {
		return;
	}

	if (bCheckboxOn) {
        nodeCheckboxOn->control.state = ENABLE_CONTROL_STATE;
		nodeCheckboxOff->control.state = INVISIBLE_CONTROL_STATE;
        drawButton(&nodeCheckboxOn->control);
	} else {
		nodeCheckboxOn->control.state = INVISIBLE_CONTROL_STATE;
		nodeCheckboxOff->control.state = ENABLE_CONTROL_STATE;
        drawButton(&nodeCheckboxOff->control);
	}
}


ResponseControl executeButtonCheckbox(Control *control) {
    ResponseControl rc;
    initResponseControl(&rc);

    switch (control->state) {
        case RELEASED_CONTROL_STATE:
			drawButton(control);
			gCheckboxState = !gCheckboxState;
			setCheckboxStates(gCheckboxState);
            if (gCheckboxState == true) {
                setEnableNextButton();
			} else {
			    setDisableNextButton();
			}
			break;
        case PRESSED_CONTROL_STATE:
            drawButton(control);
            break;
        default:
            break;
    }
    return rc;
}

void drawQuizTextInputActivated(uint32_t order) {
	uint32_t resourceSize = 0;

	Node* imageNode = pickingControlById(gGroupQuizTextEditImage.startId + order);
	if (imageNode != NULL) {
		imageNode->control.originResource = getScreenResource(ID_RESOURCE_BACKUP_QUIZ_TEXT_INPUT_ACTIVATED, &resourceSize);
		imageNode->control.originResourceSize = resourceSize;
		imageNode->control.state = ENABLE_CONTROL_STATE;
		drawImageView(&imageNode->control);
	}
}

void drawQuizTextInputError(uint32_t order) {
	uint32_t resourceSize = 0;

	Node* imageNode = pickingControlById(gGroupQuizTextEditImage.startId + order);
	if (imageNode != NULL) {
		imageNode->control.originResource = getScreenResource(ID_RESOURCE_BACKUP_QUIZ_TEXT_INPUT_ERROR, &resourceSize);
		imageNode->control.originResourceSize = resourceSize;
		imageNode->control.state = ENABLE_CONTROL_STATE;
		drawImageView(&imageNode->control);
	}
}

void drawQuizTextInputComplete(uint32_t order) {
	uint32_t resourceSize = 0;
	uint32_t textWidth = 0;
	uint32_t textHeight = 0;

	Node* textEditNode = pickingControlById(gGroupQuizTextEdit.startId + order);
	if (textEditNode != NULL) {
		getTextWidthAndHeight(textEditNode->control.textInfo.text, textEditNode->control.textInfo.font, &textWidth, &textHeight);
		clearCursor(textEditNode->control.location.x1 + textWidth, textEditNode->control.location.y1, RESTORE_MNEMONIC_TEXTINPUT_CURSOR_MARGIN);
	}

	Node* imageNode = pickingControlById(gGroupQuizTextEditImage.startId + order);
	if (imageNode != NULL) {
		imageNode->control.originResource = getScreenResource(ID_RESOURCE_BACKUP_QUIZ_TEXT_INPUT_COMPLETE, &resourceSize);
		imageNode->control.originResourceSize = resourceSize;
		imageNode->control.state = ENABLE_CONTROL_STATE;
		drawImageView(&imageNode->control);
	}
}

void drawQuizButtonEnterChecked(Control* button) {
	uint32_t checkedImageSize = 0;
	uint8_t* checkedImageBuffer = getScreenResource(ID_RESOURCE_BACKUP_QUIZ_BUTTON_ENTER_CHECKED, &checkedImageSize);
	button->extraResource = checkedImageBuffer;
	button->extraResourceSize = checkedImageSize;
	button->state = DISABLE_CONTROL_STATE;
	drawButton(button);
}

void updateQuizComplete(Control* button, uint32_t order) {
	DBG_LOG("updateQuizComplete");
	uint32_t id = 0;
	if (order == 0) {
		id = ID_CONTROL_IMAGE_VIEW_BACKUP_QUIZ_SECOND_MESSAGE;
	} else {
		id = ID_CONTROL_IMAGE_VIEW_BACKUP_QUIZ_THIRD_MESSAGE;
	}
	Node* msgNode = pickingControlById(id);
	if (msgNode != NULL) {
		msgNode->control.state = ENABLE_CONTROL_STATE;
		drawImageView(&msgNode->control);
	}
	
	Node* textEditNode = pickingControlById(gGroupQuizTextEdit.startId + order);
	if (textEditNode != NULL) {
		setFocus(&textEditNode->control, false);
		textEditNode->control.state = DISABLE_CONTROL_STATE;
		drawTextBox(&textEditNode->control);
		drawQuizTextInputComplete(order);
	}

	Node* buttonNode = pickingControlById(button->id);
	if (buttonNode != NULL) {
		buttonNode->next->control.state = DISABLE_CONTROL_STATE;
		drawButton(&buttonNode->next->control);
	}

	textEditNode = pickingControlById(gGroupQuizTextEdit.startId + order + 1);
	if (textEditNode != NULL) {
		setFocus(&textEditNode->control, true);
		textEditNode->control.state = ENABLE_CONTROL_STATE;
		drawTextBox(&textEditNode->control);
		drawQuizTextInputActivated(order + 1);
	}

	drawQuizButtonEnterChecked(button);
}

bool isLastGroupQuizTextEdit(uint32_t id) {
	if ((id - gGroupQuizTextEdit.startId) == (QUIZ_WORD_COUNT - 1)) {
		return true;
	}
	return false;
}

void clearErrorMessage(uint32_t order) {
	uint32_t id = 0;
	if (order == 0) {
		id = ID_CONTROL_IMAGE_VIEW_BACKUP_QUIZ_FIRST_WRONG_INPUT;
	} else if (order == 1) {
		id = ID_CONTROL_IMAGE_VIEW_BACKUP_QUIZ_SECOND_WRONG_INPUT;
	} else {
		id = ID_CONTROL_IMAGE_VIEW_BACKUP_QUIZ_THIRD_WRONG_INPUT;
	}

	Node* node = pickingControlById(id);
	if (node == NULL) {
		DBG_LOG("clear error message is NULL");
		return;
	}
	clearImageView(&(node->control));
}

ResponseControl executeTextEditQuizWord(Control *control) {
	DBG_LOG("executeTextEditQuizWord");
	ResponseControl rc;
	initResponseControl(&rc);

	Node* buttonNode;

	uint32_t order = 0;
	uint32_t textLen = 0;
	uint32_t textWidth = 0;
	uint32_t textHeight = 0;

	switch (control->state) {
	case UPDATED_CONTROL_STATE:
		if (control->focused == false) {
			break;
		}
		order = control->id - gGroupQuizTextEdit.startId;
		getTextWidthAndHeight(control->textInfo.text, control->textInfo.font, &textWidth, &textHeight);
		buttonNode = pickingControlById(gGroupQuizEnterButton.startId + order);
		textLen = strlen((char *)control->textInfo.text);
		if (textLen == 0) {
			updateBufferCursor(control->location.x1, control->location.y1);
			buttonNode->control.state = DISABLE_CONTROL_STATE;
			drawButton(&buttonNode->control);
		} else {
			updateBufferCursorWithMargin(control->location.x1 + textWidth, control->location.y1, RESTORE_MNEMONIC_TEXTINPUT_CURSOR_MARGIN);
			buttonNode->control.state = ENABLE_CONTROL_STATE;
			drawButton(&buttonNode->control);
		}
		clearErrorMessage(order);
		drawQuizTextInputActivated(order);
		break;
	default:
		break;
	}

	return rc;
}

uint8_t* getMnemonicFromBackupList(uint32_t index) {
	if (mnemonicList[index-1] != NULL) {
		return mnemonicList[index-1];
	}
	return NULL;
}

ResponseControl executeButtonFirstEnter(Control *control) {
	DBG_LOG("executeButtonFirstEnter");
	ResponseControl rc;
	initResponseControl(&rc);

	Node* textEditNode;
	Node* msgNode;

	uint32_t index = 0;

	switch (control->state) {
	case PRESSED_CONTROL_STATE:
		drawButton(control);
		break;

	case RELEASED_CONTROL_STATE:
		drawButton(control);
		index = gBackupQuizOrderArray[0];
		if (index <= 0 || index > (gGroupBackupList.groupSize / 2)) {
			TTY_LOG("First quiz order is invalid : %d", index);
			changeState(FAILED_TUI_STATE);
			return rc;
		}
		
		textEditNode = pickingFocusedControl(TEXT_EDIT_BOX_CONTROL_TYPE);
		if (textEditNode == NULL) {
			TTY_LOG("Focused text box is NULL");
			changeState(FAILED_TUI_STATE);
			return rc;
		}

		if (strcmp((char *)textEditNode->control.textInfo.text, (char *)getMnemonicFromBackupList(index)) == 0) {
			updateQuizComplete(control, 0);
		} else {
			msgNode = pickingControlById(ID_CONTROL_IMAGE_VIEW_BACKUP_QUIZ_FIRST_WRONG_INPUT);
			if (msgNode == NULL) {
				changeState(REQUEST_TEXT_BACKUP_FIRST_WRONG_INPUT_TUI_STATE);
			} else {
				msgNode->control.state = ENABLE_CONTROL_STATE;
				drawImageView(&msgNode->control);
			}
			drawQuizTextInputError(0);
		}
		break;
	default:
		break;
	}
	return rc;
}

ResponseControl executeButtonSecondEnter(Control *control) {
	DBG_LOG("executeButtonSecondEnter");
	ResponseControl rc;
	initResponseControl(&rc);

	Node* textEditNode;
	Node* msgNode;

	uint32_t index = 0;

	switch (control->state) {
	case PRESSED_CONTROL_STATE:
		drawButton(control);
		break;

	case RELEASED_CONTROL_STATE:
		drawButton(control);
		index = gBackupQuizOrderArray[1];
		if (index <= 0 || index > (gGroupBackupList.groupSize / 2)) {
			TTY_LOG("Second quiz order is invalid : %d", index);
			changeState(FAILED_TUI_STATE);
			return rc;
		}

		textEditNode = pickingFocusedControl(TEXT_EDIT_BOX_CONTROL_TYPE);
		if (textEditNode == NULL) {
			TTY_LOG("Focused text box is NULL");
			changeState(FAILED_TUI_STATE);
			return rc;
		}

		if (strcmp((char *)textEditNode->control.textInfo.text, (char *)getMnemonicFromBackupList(index)) == 0) {
			updateQuizComplete(control, 1);
		} else {
			msgNode = pickingControlById(ID_CONTROL_IMAGE_VIEW_BACKUP_QUIZ_SECOND_WRONG_INPUT);
			if (msgNode == NULL) {
				changeState(REQUEST_TEXT_BACKUP_SECOND_WRONG_INPUT_TUI_STATE);
			} else {
				msgNode->control.state = ENABLE_CONTROL_STATE;
				drawImageView(&msgNode->control);
			}
			drawQuizTextInputError(1);
		}
		break;
	default:
		break;
	}
	return rc;
}

ResponseControl executeButtonThirdEnter(Control *control) {
	DBG_LOG("executeButtonThirdEnter");
	ResponseControl rc;
	initResponseControl(&rc);

	Node* textEditNode;
	Node* msgNode;

	uint32_t index = 0;

	switch (control->state) {
	case PRESSED_CONTROL_STATE:
		drawButton(control);
		break;

	case RELEASED_CONTROL_STATE:
		drawButton(control);
		index = gBackupQuizOrderArray[2];
		if (index <= 0 || index > (gGroupBackupList.groupSize / 2)) {
			TTY_LOG("Third quiz order is invalid : %d", index);
			changeState(FAILED_TUI_STATE);
			return rc;
		}
		
		textEditNode = pickingFocusedControl(TEXT_EDIT_BOX_CONTROL_TYPE);
		if (textEditNode == NULL) {
			TTY_LOG("Focused text box is NULL");
			changeState(FAILED_TUI_STATE);
			return rc;
		}

		if (strcmp((char *)textEditNode->control.textInfo.text, (char *)getMnemonicFromBackupList(index)) == 0) {
			changeState(OK_TUI_STATE);
		} else {
			msgNode = pickingControlById(ID_CONTROL_IMAGE_VIEW_BACKUP_QUIZ_THIRD_WRONG_INPUT);
			if (msgNode == NULL) {
				changeState(REQUEST_TEXT_BACKUP_THIRD_WRONG_INPUT_TUI_STATE);
			} else {
				msgNode->control.state = ENABLE_CONTROL_STATE;
				drawImageView(&msgNode->control);
			}
			drawQuizTextInputError(2);
		}
		break;
	default:
		break;
	}
	return rc;
}

uint32_t drawBackupScreenQuiz() {
	DBG_LOG("drawBackupScreenQuiz");
	Control control;
	Location loc;
	uint32_t controlId = 1;
	TextInfo textInfo;

	uint32_t enableImgSize = 0;
	uint32_t pressedImgSize = 0;
	uint32_t defaultImgSize = 0;
	uint8_t* enableImgBuffer;
	uint8_t* pressedImgBuffer;
	uint8_t* defaultImgBuffer;

	Node* node = pickingControlById(ID_CONTROL_IMAGE_VIEW_BACKUP_QUIZ_FIRST_MESSAGE);
	if (node != NULL) {
		node->control.state = ENABLE_CONTROL_STATE;
		drawImageView(&node->control);
	}

	gGroupQuizEnterButton.startId = controlId;
	gGroupQuizEnterButton.groupSize = QUIZ_WORD_COUNT;
	enableImgBuffer = getScreenResource(ID_RESOURCE_BACKUP_QUIZ_BUTTON_ENTER_ENABLE, &enableImgSize);
	pressedImgBuffer = getScreenResource(ID_RESOURCE_BACKUP_QUIZ_BUTTON_ENTER_PRESSED, &pressedImgSize);
	defaultImgBuffer = getScreenResource(ID_RESOURCE_BACKUP_QUIZ_BUTTON_ENTER_DEFAULT, &defaultImgSize);
	for (uint32_t i = 0; i < QUIZ_WORD_COUNT; i++) {
		loc.x1 = BACKUP_QUIZ_TEXTINPUT_LEFT_MARGIN + BACKUP_QUIZ_TEXTINPUT_WIDTH + BACKUP_QUIZ_BUTTON_LEFT_MARGIN;
		loc.y1 = BACKUP_QUIZ_BUTTON_START_TOP_MARGIN + (i * BACKUP_QUIZ_NEXT_DISTANCE);
		initButton(&control, controlId++, loc, BACKUP_QUIZ_BUTTON_WIDTH, BACKUP_QUIZ_BUTTON_HEIGHT,
			pressedImgBuffer, pressedImgSize, enableImgBuffer, enableImgSize, defaultImgBuffer, defaultImgSize, 0);
		if (i == 0) {
			control.state = DISABLE_CONTROL_STATE;
		} else {
			control.isDrawingWhenAdded = 0;
			control.state = INVISIBLE_CONTROL_STATE;
		}

		if (i == 0) {
			addButton(&control, executeButtonFirstEnter);
		} else if (i == 1) {
			addButton(&control, executeButtonSecondEnter);
		} else {
			addButton(&control, executeButtonThirdEnter);
		}
	}

	gGroupQuizTextEditImage.startId = controlId;
	gGroupQuizTextEditImage.groupSize = QUIZ_WORD_COUNT;
	enableImgBuffer = getScreenResource(ID_RESOURCE_BACKUP_QUIZ_TEXT_INPUT_ACTIVATED, &enableImgSize);
	for (uint32_t i = 0; i < QUIZ_WORD_COUNT; i++) {
		loc.x1 = BACKUP_QUIZ_TEXTINPUT_LEFT_MARGIN;
		loc.y1 = BACKUP_QUIZ_TEXTINPUT_START_TOP_MARGIN + BACKUP_QUIZ_TEXTINPUT_HEIGHT + BACKUP_QUIZ_TEXTINPUT_LINE_DISTANCE + (i * BACKUP_QUIZ_NEXT_DISTANCE);
		initImageView(&control, controlId++, loc, 0, 0, NULL, 0, enableImgBuffer, enableImgSize);
		if (i != 0) {
			control.isDrawingWhenAdded = 0;
		}
		addImageView(&control);
	}

	gGroupQuizTextEdit.startId = controlId;
	gGroupQuizTextEdit.groupSize = QUIZ_WORD_COUNT;
	for (uint32_t i = 0; i < QUIZ_WORD_COUNT; i++) {
		loc.x1 = BACKUP_QUIZ_TEXTINPUT_LEFT_MARGIN;
		loc.y1 = BACKUP_QUIZ_TEXTINPUT_START_TOP_MARGIN + (i * BACKUP_QUIZ_NEXT_DISTANCE);
		textInfo.text = emptyString;
		textInfo.font = getScreenFontType(ID_FONT_TYPE_RESTORE_MNEMONIC_INPUT);
		initTextBox(&control, controlId++, loc, BACKUP_QUIZ_TEXTINPUT_WIDTH, BACKUP_QUIZ_TEXTINPUT_HEIGHT, NULL, 0, NULL, 0, textInfo, LEFT_CONTENT_ALIGN, VERTICAL_CENTER_CONTENT_ALIGN);
		if (i == 0) {
			setFocus(&control, TRUE);
		} else {
			control.isDrawingWhenAdded = 0;
		}
		addTextEditBox(&control, executeTextEditQuizWord);
	}

	loc.x1 = BACKUP_QUIZ_KEYPAD_START_X;
	loc.y1 = BACKUP_QUIZ_KEYPAD_START_Y;
	initKeypad(&control, loc);
	addKeypad(&control);

	return TIMA_SUCCESS;
}
