#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wiiuse/wpad.h>

#include "AnyRegionChanger.h"
#include "cert_sys.h"
#include "controller.h"
#include "detect_settings.h"
#include "dopios.h"
#include "id.h"
#include "IOSCheck.h"
#include "nand.h"
#include "patchmii_core.h"
#include "Settings.h"
#include "sysconf.h"
#include "title_install.h"
#include "tools.h"
#include "video.h"

int lang, area, game, video, region, country, eula;

const char languages[][11] = { "Japanese", "English", "German",
    "French", "Spanish", "Italian", "Dutch", "S. Chinese",
    "T. Chinese", "Korean" };
const char areas[][10] = { "Japan", "USA", "Europe", "Australia",
    "Brazil", "Taiwan", "China", "Korea", "Hong Kong", "Asia",
    "Latin Am.", "S. Africa" };
const char regions_names[][7] = { "Japan", "USA", "Europe", "Korea" };
const char vmodes[][5] = { "NTSC", "PAL", "MPAL" };
const char eulas[][7] = { "Unread", "Read" };

s32 getSettings(void) {
    lang = wiiSettings.lang;
    area = wiiSettings.area;
    game = wiiSettings.game;
    video = wiiSettings.video;
    eula = wiiSettings.eula;
    country = wiiSettings.country;
    return 0;
}

s32 saveSettings(void) {
    s32 ret = 0;
    u8 sadr[SADR_LENGTH];
    ret = Identify_SU();
    if (ret < 0) {
        printf("Unexpected Error: %s Value: %d\n", "Identify_SU", ret);
        return -1;
    }
    ret = Nand_Init();
    if (ret < 0) {
        printf("Unexpected Error: %s Value: %d\n", "Nand_Init", ret);
        return -1;
    }
    ret = SYSCONF_Init();
    if (ret < 0) {
        printf("Unexpected Error: %s Value: %d\n", "SYSCONF_Init", ret);
        return -1;
    }
    if (lang != wiiSettings.lang) ret = SYSCONF_SetLanguage(lang);
    if (ret) {
        printf("Unexpected Error: %s Value: %d\n", "SYSCONF_SetLanguage", ret);
        return -1;
    }
    if (area != wiiSettings.area) ret = SYSCONF_SetArea(area);
    if (ret) {
        printf("Unexpected Error: %s Value: %d\n", "SYSCONF_SetArea", ret);
        return -1;
    }
    if (game != wiiSettings.game) ret = SYSCONF_SetRegion(game);
    if (ret) {
        printf("Unexpected Error: %s Value: %d\n", "SYSCONF_SetRegion", ret);
        return -1;
    }
    if (video != wiiSettings.video) ret = SYSCONF_SetVideo(video);
    if (ret) {
        printf("Unexpected Error: %s Value: %d\n", "SYSCONF_SetVideo", ret);
        return -1;
    }
    if (eula != wiiSettings.eula) ret = SYSCONF_SetEULA(eula);
    if (ret) {
        printf("Unexpected Error: %s Value: %d\n", "SYSCONF_SetEULA", ret);
        return -1;
    }

    if (country != wiiSettings.country) {
        memset(sadr, 0, SADR_LENGTH);
        sadr[0] = country;
        ret = SYSCONF_Set("IPL.SADR", sadr, SADR_LENGTH);
        if (ret) {
            printf("Unexpected Error: %s Value: %d\n", "SYSCONF_Set", ret);
            return -1;
        }
    }
    printf("Saving...");
    ret = SYSCONF_SaveChanges();
    if (ret < 0) {
        printf("Unexpected Error: %s Value: %d\n", "SYSCONF_SaveChanges", ret);
        return ret;
    }
    printf("OK!\n");
    ISFS_Deinitialize();
    updateRegionSettings();
    return 0;
}

void regionChangerMenu(void) {
    static int menuItem = 0;
    u32 button = 0;
    int ret = -1;

    getSettings();
    
    initNextBuffer();
    PrintBanner();
    printf(
        "\n\n\n\t\t" WARNING_SIGN " IMPORTANT BRICK INFORMATION " WARNING_SIGN "\n");
    printf(
        "\n\t\tSemi Bricks are caused by the Console Area setting not matching\n");
    printf(
        "\t\tyour System Menu region. A semi-brick in itself is not terribly\n");
    printf(
        "\t\tharmful, but it can easily deteriorate into a full brick--there\n");
    printf("\t\tare multiple simple triggers to do so.\n");
    printf(
        "\n\t\tIn order to practice proper safety when using this application, \n");
    printf(
        "\t\tplease make sure that your Console Area and System Menu region \n");
    printf(
        "\t\tare congruent before rebooting your system. A warning will be\n");
    printf("\t\tdisplayed if they are not in agreement.\n");
    flushBuffer();
    PromptAnyKeyContinue();
    
    while (!(button & WPAD_BUTTON_B)) {
        initNextBuffer();
        PrintBanner();
        printf("\n\n\n\t\t\t\t%3s Language Setting: %s\n", (menuItem == 0)
            ? "-->" : " ", languages[lang]);
        if (wiiSettings.sysMenuRegion != AREAtoSysMenuRegion(area)) {
            printf(
                "\t\t\t\t" WARNING_SIGN " \x1b[41;1mWARNING: AREA/SysMenu MISMATCH!\x1b[40m " WARNING_SIGN "\n");
        }
        printf("\t\t\t\t%3s Console Area Setting: %s\n", (menuItem == 1)
            ? "-->" : " ", areas[area]);
        printf("\t\t\t\t%3s Game Region Setting: %s\n", (menuItem == 2)
            ? "-->" : " ", regions_names[game]);
        printf("\t\t\t\t%3s Console Video Mode: %s\n", (menuItem == 3)
            ? "-->" : " ", vmodes[video]);
        printf("\t\t\t\t\tCountry Codes: 1=JPN 49=USA 110=UK 136=KOR\n");
        printf("\t\t\t\t%3s Shop Country Code: %d\n", (menuItem == 4)
            ? "-->" : " ", country);
        printf("\t\t\t\t%3s Services EULA: %s\n\n", (menuItem == 5)
            ? "-->" : " ", (eula == SYSCONF_ENOENT) ? "Disabled " : eulas[eula]);
        printf("\t\t\t\t%3s Reload Current Settings\n", (menuItem == 6)
            ? "-->" : " ");
        printf("\t\t\t\t%3s Save Settings\n", (menuItem == 7) ? "-->" : " ");
        Console_SetPosition(ConsoleRows - 5, 0);
        horizontalLineBreak();
        printf("\n\t(%s)/(%s) (%s)/(%s)\t\tChange Selection\n", UP_ARROW,
            DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW);
        printf("\t(A)\t\t\t\t\tSelect\t\t\t\t\t(B)\tBack\n");
        printf("\t(HOME)/GC:(START)\t\tExit");
        flushBuffer();
        
        button = WaitButtons();
        if (ExitMainThread) {
            return;
        }
        if (button & WPAD_BUTTON_HOME) {
            ReturnToLoader();
        }
        if (button & WPAD_BUTTON_A) {
            if (menuItem == 6) {
                getSettings();
            } else if (menuItem == 7) {
                ret = saveSettings();
                if (ret < 0) {
                    ISFS_Deinitialize();
                    PromptAnyKeyContinue();
                    return;
                }
            }
        }

        if (button & WPAD_BUTTON_LEFT) {
            if (menuItem == 0) {
                lang--;
            } else if (menuItem == 1) {
                area--;
            } else if (menuItem == 2) {
                game--;
            } else if (menuItem == 3) {
                video--;
            } else if (menuItem == 4) {
                country--;
                if (eula >= 0) eula = 0;
            } else if (menuItem == 5) {
                if (eula >= 0) eula = !eula;
            }
        }

        if (button & WPAD_BUTTON_RIGHT) {
            if (menuItem == 0) {
                lang++;
            } else if (menuItem == 1) {
                area++;
            } else if (menuItem == 2) {
                game++;
            } else if (menuItem == 3) {
                video++;
            } else if (menuItem == 4) {
                country++;
                if (eula >= 0) eula = 0;
            } else if (menuItem == 5) {
                if (eula >= 0) eula = !eula;
            }
        }

        if (button & WPAD_BUTTON_DOWN) menuItem++;
        if (button & WPAD_BUTTON_UP) menuItem--;
        
        if (menuItem > 7) menuItem = 0;
        if (menuItem < 0) menuItem = 7;
        
        if (lang < 0) lang = 9;
        if (area < 0) area = 11;
        if (game < 0) game = 3;
        if (video < 0) video = 2;
        if (country < 0) country = 255;
        
        if (lang > 9) lang = 0;
        if (area > 11) area = 0;
        if (game > 3) game = 0;
        if (video > 2) video = 0;
        if (country > 255) country = 0;
    }
}
