/*
 *--------------------------------------
 * Program Name:
 * Author:
 * License:
 * Description:
 *--------------------------------------
*/

/* Keep these headers */
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <tice.h>

/* Standard headers (recommended) */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <graphx.h>
#include <keypadc.h>

int8_t map[2112], level = 1, numPacks = 0;

typedef struct {
    uint16_t x, y;
} player_t;
player_t player;

typedef struct {
    uint16_t x,y;
    uint8_t direction;
    gfx_sprite_t *background;
} enemy_t;
enemy_t enemies[40];

int levelSize = 2116;

float elapsed, hTime = 999.9, writeTime = 0.00;
bool play = true, quit = false, win = false, first = true;
char str[10], curPack[10];
real_t elapsed_real, bestTime_real;
ti_var_t file;
const char search_String[] = "MMZ";

char packs[16][10];

void menu();
void init_Map();
void init_enemies(int x, int dir, int enemyNumber);
void init_Player(int i);
void updateEnemies();
void updatePlayer();
void updateView(kb_key_t key);
void findAppvars();
void selectAppvar();
void genNewMap();
void levelEditor();
void printBox(int xPos, int yPos, int boxNum);
bool saveOptions();
bool saveAs();


void main(void) {
    int iMax, i;
    srand(rtc_Time());
    gfx_Begin();
    gfx_SetDrawBuffer();
    findAppvars();
    menu();
    iMax = sizeof(enemies)/sizeof(enemy_t);
    for(i = 0; i < iMax; i++){
        if(enemies[i].x == 0){iMax = i;}
    }
    while(play && !(kb_Data[6] & kb_Clear) && !quit){
        updatePlayer();
        updateEnemies(iMax);
        if((map[(int)(player.x / 5) + 48 * (int)(player.y / 5)] == 14) || (map[(int)((player.x + 4) / 5) + 48 * (int)(player.y / 5)] == 14) || (map[(int)((player.x + 4) / 5) + 48 * (int)((player.y + 4) / 5)] == 14) || (map[(int)(player.x / 5) + 48 * (int)((player.y + 4) / 5)] == 14)){
            timer_Control = TIMER1_DISABLE;
            gfx_SetColor(0);
            gfx_FillRectangle(60, 70, 122, 30);
            gfx_SetColor(255);
            gfx_Rectangle(60, 70, 122, 30);
            gfx_PrintStringXY("Congratulations!", 64, 74);
            gfx_PrintStringXY("Your Time: ", 64, 86);
            elapsed = (float)atomic_load_increasing_32(&timer_1_Counter) / 32768;
            elapsed_real = os_FloatToReal(elapsed <= 0.001f ? 0.0f : elapsed);
            os_RealToStr(str, &elapsed_real, 8, 1, 2);
            gfx_PrintStringXY(str,136,86);
            gfx_SwapDraw();
            while(!(kb_Data[kb_group_1] & kb_2nd)){kb_Scan();}
            while(kb_Data[kb_group_1] & kb_2nd){kb_Scan();}
            ti_CloseAll();
            if(elapsed < hTime || hTime < 0.05){
                file = ti_Open(curPack, "r+");
                ti_Seek(levelSize * (level - 1) + sizeof(search_String) + sizeof(map), 0, file);
                ti_Write(&elapsed, sizeof(elapsed), 1, file);
                ti_CloseAll();
                hTime = elapsed;
            }
            menu();
            iMax = sizeof(enemies)/sizeof(enemy_t);
            for(i = 0; i < iMax; i++){
                if(enemies[i].x == 0){iMax = i;}
            }
        }
        if(gfx_GetPixel(player.x, player.y) == 192 || gfx_GetPixel(player.x + 4, player.y) == 192 || gfx_GetPixel(player.x + 4, player.y + 4) == 192 || gfx_GetPixel(player.x, player.y + 4) == 192){
            timer_Control = TIMER1_DISABLE;
            gfx_SetColor(0);
            gfx_FillRectangle(60, 70, 122, 30);
            gfx_SetColor(255);
            gfx_Rectangle(60, 70, 122, 30);
            gfx_PrintStringXY("You got caught!", 70, 78);
            gfx_SwapDraw();
            while(!(kb_Data[kb_group_1] & kb_2nd)){kb_Scan();}
            while(kb_Data[kb_group_1] & kb_2nd){kb_Scan();}
            menu();
            iMax = sizeof(enemies)/sizeof(enemy_t);
            for(i = 0; i < iMax; i++){
                if(enemies[i].x == 0){iMax = i;}
            }
        }
    }
    ti_CloseAll();
    gfx_End();
    findAppvars();
    for(i = 0; i < numPacks; i++){
        file = ti_Open(packs[i], "r");
        ti_SetArchiveStatus(true, file);
        ti_Close(file);
    }
}

void menu(){
    int i, choice = 0;
    bool key, prevKey = false, startGame = false;
    
    timer_1_Counter = 0.0;
    gfx_SetClipRegion(0,0,320,240);
    gfx_ZeroScreen();
    for(i = 0; i < 15; i++){
        gfx_SetTextFGColor(33);
        gfx_PrintStringXY("?",rand() % 50 + 248, rand() % 170 + 30);
        gfx_SetTextFGColor(107);
        gfx_PrintStringXY("?",rand() % 50 + 248, rand() % 170 + 30);
    }
    gfx_SetColor(255);
    gfx_SetTextScale(7,7);
    gfx_PrintStringXY("?",100,70);
    gfx_SetTextScale(1,1);
    gfx_Rectangle_NoClip(244,6,72,215);
    gfx_Rectangle_NoClip(4, 220, 312, 16);
    gfx_SetTextFGColor(255);
    gfx_SetTextBGColor(0);
    gfx_SetTextTransparentColor(0);
    gfx_PrintStringXY("Mystery",250,10);
    gfx_PrintStringXY("Maze",264,22);
    gfx_PrintStringXY("Play", 264, 40);
    gfx_PrintStringXY("Change", 256, 65);
    gfx_PrintStringXY("Level", 262, 75);
    gfx_PrintStringXY("Load", 264, 95);
    gfx_PrintStringXY("Pack", 264, 105);
    gfx_PrintStringXY("New", 268, 130);
    gfx_PrintStringXY("Edit", 266, 160);
    gfx_PrintStringXY("Exit", 266, 190);
    gfx_PrintStringXY("Pack: ", 6, 224);
    gfx_PrintStringXY("Level:", 120, 224);
    gfx_PrintStringXY("Best: ",220, 224);
    
    do{
        gfx_SetColor(0);
        gfx_FillRectangle_NoClip(247,40, 6, 170);
        gfx_FillRectangle_NoClip(308,40, 6, 170);
        gfx_FillRectangle_NoClip(164,224,40,10);
        gfx_FillRectangle_NoClip(258,224,55,10);
        file = ti_Open(curPack, "r");
        if(file){
            gfx_PrintStringXY(&curPack, 44, 224);
            bestTime_real = os_FloatToReal(hTime <= 0.001f ? 0.0f : hTime);
            os_RealToStr(str, &bestTime_real, 8, 1, 2);
            gfx_PrintStringXY(str,258,224);
        }
        gfx_SetTextXY(164, 224);
        gfx_PrintInt(level, 2);
        key = kb_AnyKey();
        if(key && !prevKey){
            if(kb_Data[7] & kb_Up && curPack != ""){
                choice = (choice - 1 == -1 ? 5 : choice - 1);
            }
            if(kb_Data[7] & kb_Down){
                choice = (choice + 1) % 6;
            }
            if(kb_Data[1] & kb_2nd){
                switch(choice){
                    case 0:
                    if(file)
                    startGame = true;
                    init_Map();
                    timer_Control = TIMER1_ENABLE | TIMER1_32K | TIMER1_UP;
                    break;
                    case 2:
                    selectAppvar();
                    break;
                    case 3:
                    genNewMap();
                    levelEditor();
                    break;
                    case 4:
                    if(file)
                    levelEditor();
                    break;
                    case 5:
                    quit = true;
                    break;
                }
            }
        
            if(choice == 1){
                if(kb_Data[7] & kb_Right && level < ti_GetSize(file)/levelSize){
                    
                    level++;
                    hTime = 0;
                }
                if(kb_Data[7] & kb_Left && level > 1){
                    level--;
                    hTime = 0;
                }
                ti_Seek(levelSize * (level - 1) + sizeof("MMZ") / sizeof(char), 0, file);
                ti_Read(&map, sizeof(map),1,file);
                ti_Read(&hTime,sizeof(float),1, file);
            }
        }
        if(choice == 1){gfx_PrintStringXY("<>", 180,224);}
        gfx_PrintStringXY(">", 247, choice * 30 + 40);
        gfx_PrintStringXY("<", 308, choice * 30 + 40);
        prevKey = key;
        gfx_SwapDraw();
        gfx_BlitScreen();
        ti_CloseAll();
    }while(!(kb_Data[kb_group_6] & kb_Clear) && !startGame && !quit);
    
}
void init_Map(){
    int i;
    int numEnemy = 0;
    for(i = 0; i < 40; i++){
        enemies[i].x = 0;
        enemies[i].y = 0;
        enemies[i].direction = 0;
    }
    for(i = 0; i < sizeof(map); i++){
        switch (map[i]){
            case 0:
            init_Player(i);
            break;
            case 6:
            init_enemies(i,0,numEnemy);
            numEnemy++;
            break;
            case 7:
            init_enemies(i,1,numEnemy);
            numEnemy++;
            break;
            case 8:
            init_enemies(i,2,numEnemy);
            numEnemy++;
            break;
            case 9:
            init_enemies(i,3,numEnemy);
            numEnemy++;
            break;
        }
    }
    gfx_SetColor(0);
}

void init_enemies(int x, int dir, int enemyNumber){
    enemies[enemyNumber].x = 5 * (x % 48);
    enemies[enemyNumber].y = 5 * (int) (x / 48);
    enemies[enemyNumber].direction = dir;
    enemies[enemyNumber].background = gfx_MallocSprite(5,5);
    gfx_GetSprite_NoClip(enemies[enemyNumber].background, enemies[enemyNumber].x, enemies[enemyNumber].y);
}

void init_Player(int x){
    player.x = 5 * (x % 48);
    player.y = 5 * ((int) (x / 48));
}
void updateEnemies(int iMax){
    int i;
    gfx_SetClipRegion(0, 0, 240, 220);
    for(i = 0; i < iMax; i++){gfx_Sprite(enemies[i].background, enemies[i].x, enemies[i].y);}
    for(i = 0; i < iMax; i++){
        enemy_t *this_enemy = &enemies[i];
        if(this_enemy->x % 5 == 0 && this_enemy->y % 5 == 0){
            switch(map[(int)(this_enemy->x / 5) + (48 * (int)(this_enemy->y / 5))]){
                case 3:
                this_enemy->direction = (this_enemy->direction + 1) % 4;
                break;
                case 4:
                this_enemy->direction = (this_enemy->direction + 2) % 4;
                break;
                case 5:
                this_enemy->direction = (this_enemy->direction + 3) % 4;
                break;
                case 10:
                if(this_enemy->direction == 2){this_enemy->direction = 1;}
                else if(this_enemy->direction == 3){this_enemy->direction = 0;}
                break;
                case 11:
                if(this_enemy->direction == 1){this_enemy->direction = 0;}
                else if(this_enemy->direction == 2){this_enemy->direction = 3;}
                break;
                case 12:
                if(this_enemy->direction == 0){this_enemy->direction = 3;}
                else if(this_enemy->direction == 1){this_enemy->direction = 2;}
                break;
                case 13:
                if(this_enemy->direction == 3){this_enemy->direction = 2;}
                else if(this_enemy->direction == 0){this_enemy->direction = 1;}
                break;
            }
        }
        
        switch(this_enemy->direction){
            case 0:
            this_enemy->x++;
            break;
            case 1:
            this_enemy->y++;
            break;
            case 2:
            this_enemy->x--;
            break;
            case 3:
            this_enemy->y--;
            break;
        }
        gfx_GetSprite(this_enemy->background, this_enemy->x, this_enemy->y);
        
    }
    for(i = 0; i < iMax; i++){
        int xDist = player.x - enemies[i].x, yDist = player.y - enemies[i].y;
        if(sqrt(xDist * xDist + yDist * yDist) < 50){
            gfx_SetColor(192);
            gfx_FillRectangle(enemies[i].x, enemies[i].y, 5, 5);
        }
    }
    gfx_SwapDraw();
    gfx_BlitScreen();
}

void updatePlayer(){
    kb_key_t key;
    gfx_SetClipRegion(player.x - 5, player.y - 5,player.x + 10,player.y + 10);
    kb_Scan();
    key = kb_Data[7];
    updateView(key);
    gfx_SetColor(255);
    gfx_FillRectangle(player.x,player.y,5,5);
    if(map[(int)(player.x / 5) + (48 * (int)((player.y + 4)/5)) + 1] != 2 && map[(int)(player.x / 5) + (48 * (int)(player.y/5)) + 1] != 2 && (key & kb_Right)){player.x++;} //Move right if possible
    if(map[(int)((player.x  + 4)/ 5) + (48 * (int)((player.y + 4)/5 - 1))] != 2 && map[(int)(player.x / 5) + (48 * (int)((player.y + 4)/5 - 1))] != 2 && (key & kb_Up)){player.y--;} //Move up if possible
    if(map[(int)(player.x / 5) + (48 * (int)(player.y/5 + 1))] != 2 && map[(int)((player.x + 4) / 5 - 1) + (48 * (int)(player.y/5 + 1)) + 1] != 2 && (key & kb_Down)){player.y++;} //Move down if possible
    if(map[(int)((player.x + 4) / 5) + (48 * (int)((player.y + 4) / 5)) - 1] != 2 && map[(int)((player.x + 4) / 5) + (48 * (int)(player.y/5)) - 1] != 2 && (key & kb_Left)){player.x--;} //Move left if possible

    gfx_SetColor(7);
    gfx_FillRectangle(player.x,player.y,5,5);
}

void updateView(kb_key_t key){
    int i = 0, startIndex = ((int)(player.x - 10) / 5) + 48 * (int)((player.y - 10) / 5), printPosX = player.x - 10 - player.x % 5, printPosY = player.y - 10 - player.y % 5;
    int xOffset, yOffset;
    gfx_SetColor(255);
    gfx_FillRectangle(player.x - 5, player.y - 5, 15, 15);
    xOffset = (player.x < 10 && player.x > 5 ? 5 : 0);
    yOffset = (player.y < 10 && player.y > 5 ? 5 : 0);
    for(i = 0; i < 25; i++){
            switch(map[startIndex + (i % 5) + 48 * (int)(i / 5)]){
            case 1:
            gfx_SetColor(255);
            break;
            case 2:
            gfx_SetColor(0);
            break;
            case 14:
            gfx_SetColor(31);
            break;
            default:
            gfx_SetColor(255);
            break;
        }
        gfx_FillRectangle(printPosX + ((i % 5)) * 5 + xOffset, printPosY + ((int)(i / 5)) * 5 + yOffset, 5, 5);
    }
}

void findAppvars(){
    char *varName;
    uint8_t *search_Pos = NULL;
    while ((varName = ti_Detect(&search_Pos, "MMZ"))) {
        strcpy(&packs[numPacks++], varName);
    }
}

void selectAppvar(){
    int choice = 0, i;
    bool key, prevKey = false;
    ti_CloseAll();
    for(i = 0; i < numPacks; i++){
        gfx_PrintStringXY(packs[i], 44, 210 - (i * 10));
    }
    gfx_SetColor(255);
    gfx_Rectangle(34,216 - numPacks * 10, 78, numPacks * 10 + 5);
    while(kb_Data[1] & kb_2nd){kb_Scan();}
    do{
        gfx_SetColor(0);
        gfx_FillRectangle_NoClip(36, 216 - numPacks * 10 + 2, 8, numPacks * 10);
        key = kb_AnyKey();
        if(key && !prevKey){
            if(kb_Data[7] & kb_Up){choice = (choice + 1) % numPacks;}
            else if(kb_Data[7] & kb_Down){choice = (choice - 1 == -1 ? numPacks - 1 : choice - 1);}
            else if(kb_Data[1] & kb_2nd){break;}
        }
        prevKey = key;
        gfx_PrintStringXY(">", 36, 210 - choice * 10);
        gfx_SwapDraw();
        gfx_BlitScreen();
    }while(!(kb_Data[kb_group_6] & kb_Clear));
    file = ti_Open(packs[choice], "r");
    if(file){
        ti_GetName(curPack, file);
        ti_Seek(levelSize * (level - 1) + sizeof("MMZ"), 0, file);
        ti_Read(&map, sizeof(map),1,file);
        ti_Read(&hTime,sizeof(float),1, file);
        level = 1;
    }
    while(kb_Data[1] & kb_2nd){kb_Scan();}
    gfx_SetColor(0);
    gfx_FillRectangle_NoClip(34, 216 - numPacks * 10, 80, numPacks * 10 + 4);
    gfx_FillRectangle_NoClip(44, 224, 70, 10);
    ti_CloseAll();
}

void levelEditor(){
    int i, choice = 0, cursorXPos = 120, cursorYPos = 110;
    bool editing = true, key, prevKey = false, save = true;
    gfx_ZeroScreen();
    for(i = 0; i < 2112; i++){
        printBox(i % 48 * 5, 5 * (int)(i / 48), map[i]);
    }
    gfx_SetColor(255);
    gfx_Rectangle_NoClip(244,6,72,215);
    gfx_PrintStringXY("0: Spawn", 256,10);
    gfx_PrintStringXY("1: Open", 256,22);
    gfx_PrintStringXY("2: Wall", 256,34);
    gfx_PrintStringXY("3: TurnR", 256,46);
    gfx_PrintStringXY("4: 180", 256,58);
    gfx_PrintStringXY("5: TurnL", 256,70);
    gfx_PrintStringXY("6: EnmyR", 256,82);
    gfx_PrintStringXY("7: EnmyD", 256,94);
    gfx_PrintStringXY("8: EnmyL", 256,106);
    gfx_PrintStringXY("9: EnmyU", 256,118);
    gfx_PrintStringXY("TogRD", 270,130);
    gfx_PrintStringXY("TogRU", 270,142);
    gfx_PrintStringXY("TogLU", 270,154);
    gfx_PrintStringXY("TogLD", 270,166);
    gfx_PrintStringXY("Goal", 271,178);
    gfx_PrintStringXY("[Graph]: Save", 230, 228);
    for(i = 0; i < 15; i++){
        printBox(248, 11 + 12 * i, i);
    }
    do{
        printBox(cursorXPos, cursorYPos, map[cursorXPos / 5 + 48 * cursorYPos / 5]);
        gfx_SetColor(0);
        gfx_Rectangle_NoClip(247, 10 + 12 * choice, 7, 7);
        gfx_FillRectangle_NoClip(4, 228, 224, 8);
        key = kb_AnyKey();
        if(key && !prevKey){
            switch (kb_Data[1]){
                case kb_Mode:
                choice = (choice == 0 ? 14 : choice - 1);
                break;
                case kb_2nd:
                map[cursorXPos / 5 + 48 * cursorYPos / 5] = choice;
                save = false;
                break;
                case kb_Graph:
                save = saveOptions();
                for(i = 0; i < 2112; i++){
                    printBox(i % 48 * 5, 5 * (int)(i / 48), map[i]);
                }
                break;
            }
            switch(kb_Data[3]){
                case kb_0:
                choice = 0;
                break;
                case kb_1:
                choice = 1;
                break;
                case kb_4:
                choice = 4;
                break;
                case kb_7:
                choice = 7;
                break;
                case kb_GraphVar:
                choice = (choice + 1) % 15;
                break;
            }
            switch(kb_Data[4]){
                case kb_2:
                choice = 2;
                break;
                case kb_5:
                choice = 5;
                break;
                case kb_8:
                choice = 8;
                break;
            }
            switch(kb_Data[5]){
                case kb_3:
                choice = 3;
                break;
                case kb_6:
                choice = 6;
                break;
                case kb_9:
                choice = 9;
                break;
            }
            switch(kb_Data[7]){
                case kb_Up:
                cursorYPos = (cursorYPos == 5 ? 210 : cursorYPos - 5);
                break;
                case kb_Down:
                cursorYPos = (cursorYPos == 210 ? 5 : cursorYPos + 5);
                break;
                case kb_Left:
                cursorXPos = (cursorXPos == 5 ? 230 : cursorXPos - 5);
                break;
                case kb_Right:
                cursorXPos = (cursorXPos == 230 ? 5 : cursorXPos + 5);
                break;
            }
            if(kb_Data[6] & kb_Clear){
                if(save){editing = false;}
                else{
                    gfx_PrintStringXY("Not saved! Press [clear] to exit", 4, 228);
                    gfx_SwapDraw();
                    gfx_BlitScreen();
                    while(kb_AnyKey());
                    key = false;
                    while(!key){key = kb_AnyKey();}
                    if(kb_Data[6] & kb_Clear) editing = false;
                }
            }
        }
        prevKey = key;
        gfx_SetColor(66);
        gfx_Rectangle_NoClip(cursorXPos, cursorYPos, 5, 5);
        gfx_SetColor(255);
        gfx_Rectangle_NoClip(247, 10 + 12 * choice, 7, 7);
        gfx_SwapDraw();
        gfx_BlitScreen();


    }while(editing);
    

    while(!os_GetCSC());

}

void printBox(int xPos, int yPos, int boxNum){
    gfx_SetColor(7);
    if(boxNum > 0) gfx_SetColor(255);
    if(boxNum > 1) gfx_SetColor(0);
    if(boxNum > 2) gfx_SetColor(248);
    if(boxNum > 5 && boxNum < 10) gfx_SetColor(224);
    if(boxNum == 14) gfx_SetColor(31);
    if(boxNum > 14) gfx_SetColor(255);
        
    gfx_FillRectangle_NoClip(xPos, yPos, 5, 5);
    gfx_SetColor(0);
    if(boxNum == 3 || boxNum == 6) gfx_FillTriangle_NoClip(xPos + 2, yPos, xPos + 4,  yPos + 2, xPos + 2,  yPos + 4);
    if(boxNum == 4 || boxNum == 7) gfx_FillTriangle_NoClip(xPos, yPos + 2, xPos + 4,  yPos + 2, xPos + 2,  yPos + 4);
    if(boxNum == 5 || boxNum == 8) gfx_FillTriangle_NoClip(xPos + 2, yPos, xPos,  yPos + 2, xPos + 2,  yPos + 4);
    if(boxNum == 9) gfx_FillTriangle_NoClip(xPos, yPos + 2, xPos + 4,  yPos + 2, xPos + 2,  yPos);
    if(boxNum == 3 || (boxNum > 11 && boxNum < 14)) gfx_HorizLine(xPos, yPos + 2, 3);
    if(boxNum == 4 || boxNum == 11 || boxNum == 12) gfx_VertLine(xPos + 2, yPos, 3);
    if(boxNum == 6 || boxNum == 10 || boxNum == 11 || boxNum == 5) gfx_HorizLine(xPos + 2, yPos + 2, 3);
    if(boxNum == 10 || boxNum == 13) gfx_VertLine(xPos + 2, yPos + 2, 3);
}

void genNewMap(){
    int i = 0;
    for(i = 0; i < 2112; i++){
        map[i] = 1;
        if(i < 48 || i % 48 == 0 || i % 48 == 47 || i > 2064){
            map[i] = 2;
        }
    }
}

bool saveOptions(){
    uint8_t i, packChoice = 0, levelChoice = 1;
    bool key, prevKey = false, selectingPack = true;
    char newPackName[10];
    gfx_SetColor(0);
    gfx_FillRectangle_NoClip(8, 8, 82, numPacks * 10 + 19);
    gfx_SetColor(255);
    gfx_Rectangle_NoClip(10, 10,  78, numPacks * 10 + 15);
    for(i = 0; i < numPacks; i++){
        gfx_PrintStringXY(packs[i], 20, 14 + 10 * i);
    }
    gfx_PrintStringXY("NEW", 20, numPacks * 10 + 15);
    do{
        gfx_SetColor(0);
        gfx_FillRectangle_NoClip(12, 12, 8, numPacks * 10 + 10);
        key = kb_AnyKey();
        if(key && !prevKey){
            switch(kb_Data[7]){
                case kb_Down:
                packChoice = (packChoice + 1) % (numPacks + 1);
                break;
                case kb_Up:
                packChoice = (packChoice == 0 ? numPacks + 1 : packChoice - 1);
                break;
            }
            if(kb_Data[1] & kb_2nd) {
                if(packChoice == numPacks){
                    return saveAs();
                }
                selectingPack = false;
            }
            if(kb_Data[6] & kb_Clear) return false;
        }
        prevKey = key;
        gfx_PrintStringXY(">", 12, 14 + 10 * packChoice);
        gfx_SwapDraw();
        gfx_BlitScreen();
    }while(selectingPack);
    ti_CloseAll();
    file = ti_Open(packs[packChoice], "r+");
    if(file){
        ti_GetName(curPack, file);
        gfx_SetColor(0);
        gfx_FillRectangle_NoClip(90, 8, 118, 18);
        gfx_SetColor(255);
        gfx_Rectangle_NoClip(88, 10, 116, 14);
        gfx_PrintStringXY("Level:", 92, 14);
        do{
            gfx_SetColor(0);
            gfx_FillRectangle_NoClip(142, 14, 20, 8);
            key = kb_AnyKey();
            if(key && !prevKey){
                switch(kb_Data[7]){
                    case kb_Right:
                    if(level < ti_GetSize(file)/levelSize + 1) level++;
                    break;
                    case kb_Left:
                    if(level > 1) level--;
                    break;
                }
                if(kb_Data[1] & kb_2nd){
                    if(level == ti_GetSize(file) / levelSize + 1){
                        // ti_Resize(ti_GetSize(file) + levelSize, file);
                        ti_Seek(0, 2, file);
                        // ti_Write(&search_String, sizeof(search_String), 1, file);
                    }
                    else{ti_Seek(levelSize * (level - 1) + sizeof("MMZ") / sizeof(char), 0, file);}
                    ti_Write(&map, sizeof(map), 1, file);
                    ti_Write(&writeTime, sizeof(float), 1, file);
                    ti_CloseAll();
                    return true;
                }
            }
            prevKey = key;
            gfx_SetTextXY(142, 14);
            gfx_PrintInt(level, 2);
            gfx_SwapDraw();
            gfx_BlitScreen();
        }while(!(kb_Data[6] & kb_Clear));
    }
    return false;
}
bool saveAs(){
    uint8_t i = 0, skKey;
    const char *chars = "\0\0\0\0\0\0\0\0\0\0\0WRMH\0\0\0\0VQLG\0\0\0ZUPKFC\0\0YTOJEB\0\0XSNIDA\0\0\0\0\0\0\0\0\0";
    char newPackName[9];
    while(os_GetCSC());
    gfx_SetColor(0);
    gfx_FillRectangle_NoClip(90, 8, 138, 19);
    gfx_SetColor(255);
    gfx_Rectangle_NoClip(88, 10, 136, 15);
    gfx_PrintStringXY("Name:", 92, 14);
    gfx_SetColor(0);
    while(((skKey = os_GetCSC()) != sk_Enter) || i < 2){
        gfx_FillRectangle_NoClip(136, 14, 44, 8);
        if(chars[skKey] && i < 8){
            newPackName[i++] = chars[skKey];
        }
        if(skKey == sk_Del){
            newPackName[i--] = '\0';
        }
        if(skKey == sk_Clear) return false;
        newPackName[i] = '\0';
        gfx_PrintStringXY(newPackName, 136, 14);
        gfx_SwapDraw();
        gfx_BlitScreen();
    }
    
    file = ti_Open(newPackName, "w");
    ti_Write(&search_String, sizeof(search_String), 1, file);
    ti_Write(map, sizeof(map), 1, file);
    ti_Write(&writeTime, sizeof(float), 1, file);
    ti_CloseAll();
    return true;
}
/*
KEEP BORDER WALLS
0: Start Position
1: Open Space
2: Wall
3: Enemy Turn Right
4: Enemy Turn Around
5: Enemy Turn Left
6: Enemy Spawn Face Right
7: Enemy Spawn Face Down
8: Enemy Spawn Face Left
9: Enemy Spawn Face Up
10:|¯   (Toggle Right/Down)
11:|_   (Toggle Right/Up)
12:_|   (Toggle Left/Up)
13:¯|   (Toggle Left/Down)
14:Goal
*/