#include <os.h>
#include "filebrowser.h"
#include "output.h"

#define DIR_HEIGHT (CHAR_HEIGHT + 10)
#define DIR_DIRLIST_DIST CHAR_HEIGHT
#define FILENAME_WIDTH 200
#define FILEDATE_WIDTH 0
#define FILESIZE_WIDTH (SCREEN_WIDTH - FILENAME_WIDTH - FILEDATE_WIDTH)

#define FILES_SHOWN ((SCREEN_HEIGHT - DIR_HEIGHT) / CHAR_HEIGHT - 1)

#define MENU_SELECTION_COLOR (has_colors?0b011101111111111:0x0)

#define INPUTPAUSE 50

//TODO: display long directory names correctly

//some parts are adapted from hoffa's code

int is_dir(const char *path) {
//	struct stat filestat;
//	stat(path, &filestat);
//	printf("%s %i", path, filestat.st_mode);
//	return S_ISDIR(filestat.st_mode);
    int isdir = 0;
    FILE* f = fopen(path, "r");
    if(f == NULL)
        isdir = 1;
    fclose(f);
    return isdir;
}

/*void get_filesize(const char *path, char* buffer){
    struct stat filestat;
    stat(path, &filestat);
    int size = filestat.st_size;
    const char units[4][3] = {"B\0", "kB\0", "MB\0", "GB\0"};
    int i = 0;
    while (size >= 1024) {
        size /= 1024;
        ++i;
    }
    sprintf(buffer, "%d%s", size + 1, units[i]);
}*/

/*int get_filenames(const char* folder, char** result){
    DIR* dp;
    struct dirent* entryp;
    int i = 0;
    if((dp = opendir(folder)) == NULL){
        printf("opendir error\n");
        return -1;
    }
    while((entryp = readdir(dp)) != NULL){
        char* dirname = (char*) malloc(strlen(entryp->d_name)+1);
        strcpy(dirname, entryp->d_name);
        result[i] = dirname;
        i++;
    }
    return i;
}*/

int get_filenames_NU(char* folder, char** result){
    chdir(folder);
    struct dstat dir;
    int i = 0;
    if((NU_Get_First(&dir, "*.*"))){
        printf("NU_Get_First error\n");
        NU_Done(&dir);
        abort();
    }
    do {
        char* dirname = (char*) malloc(strlen(dir.filepath) + 1);
        strcpy(dirname, dir.filepath);
        result[i] = dirname;
        i++;
    } while (NU_Get_Next(&dir) == 0);
    NU_Done(&dir);
    return i;
}

int filebrowser(uint8_t* scrbuf, char* file){
    char currentdir[FILENAME_MAX];
    char* filenames[1024];
    int num_files;
    int filescroll = 0;
    int fileselected = 0;
    int i;
    int inputpause = 0;
    NU_Current_Dir("A:", currentdir);
    num_files = get_filenames_NU(currentdir, filenames);
    if(num_files == -1)
        return 1;
    while(1){
        //disp:
        memset(scrbuf, 0xFF, SCREEN_BYTES_SIZE);
        dispHorizLine(scrbuf, 0, DIR_HEIGHT-1, 320, 0);
        dispString(scrbuf, 4, (DIR_HEIGHT-CHAR_HEIGHT)/2, currentdir);
        for(i = filescroll; i < filescroll + FILES_SHOWN && i < num_files; i++){

            //disp file symbol
            if(is_dir(filenames[i]) && strcmp(filenames[i], ".") && strcmp(filenames[i], ".."))
                putChar(scrbuf, CHAR_WIDTH*2, DIR_HEIGHT+DIR_DIRLIST_DIST+(i-filescroll)*CHAR_HEIGHT, '\\');
            //disp filename, filesize and selection
            if(i != fileselected){
                dispString(scrbuf, CHAR_WIDTH*3, DIR_HEIGHT+DIR_DIRLIST_DIST+(i-filescroll)*CHAR_HEIGHT, filenames[i]);
                /*if(!is_dir(filenames[i])){
                    char size[10];
                    get_filesize(filenames[i], size);
                    dispString(scrbuf, FILENAME_WIDTH, DIR_HEIGHT+DIR_DIRLIST_DIST+(i-filescroll)*CHAR_HEIGHT, size);
                }*/
            }
            else{
                filledRect(scrbuf, CHAR_WIDTH*3, DIR_HEIGHT+DIR_DIRLIST_DIST+(i-filescroll)*CHAR_HEIGHT-1, SCREEN_WIDTH - CHAR_WIDTH*4, CHAR_HEIGHT+2, MENU_SELECTION_COLOR);
                dispStringColor(scrbuf, CHAR_WIDTH*3, DIR_HEIGHT+DIR_DIRLIST_DIST+(i-filescroll)*CHAR_HEIGHT, filenames[i], has_colors?0xFFFF:0xF, MENU_SELECTION_COLOR);
                /*if(!is_dir(filenames[i])){
                    char size[10];
                    get_filesize(filenames[i], size);
                    dispStringColor(scrbuf, FILENAME_WIDTH, DIR_HEIGHT+DIR_DIRLIST_DIST+(i-filescroll)*CHAR_HEIGHT, size, has_colors ? 0xFFFF : 0xF, MENU_SELECTION_COLOR);
                }*/
            }

        }
        memcpy(SCREEN_BASE_ADDRESS, scrbuf, SCREEN_BYTES_SIZE);

        //input:
        if(any_key_pressed() && inputpause <= 0){
            inputpause = INPUTPAUSE;
            if(isKeyPressed(KEY_NSPIRE_ESC))
                break;
            if(isKeyPressed(KEY_NSPIRE_ENTER)){
                if(is_dir(filenames[fileselected])){
                    chdir(filenames[fileselected]);
                    filescroll = 0;
                    fileselected = 0;
                    NU_Current_Dir("A:", currentdir);
                    for(i = 0; i < num_files; i++)
                        free(filenames[i]);
                    num_files = get_filenames_NU(currentdir, filenames);
                }
                else{
                    strcpy(file, currentdir);
                    strcpy(file+strlen(currentdir), filenames[fileselected]);
                    for(i = 0; i < num_files; i++)
                        free(filenames[i]);
                    chdir("/documents/");
                    printf("%s", file);
                    return 0;
                }
            }
            if(isKeyPressed(KEY_NSPIRE_UP)){
                fileselected--;
                if(fileselected < 0){
                    fileselected = num_files - 1;
                    filescroll = num_files - FILES_SHOWN;
                    if(filescroll < 0)
                        filescroll = 0;
                }
                else if(fileselected - filescroll <  0)
                    filescroll--;
            }
            if(isKeyPressed(KEY_NSPIRE_DOWN)){
                fileselected++;
                if(fileselected >= num_files){
                    fileselected = 0;
                    filescroll = 0;
                }
                else if(fileselected - filescroll >= FILES_SHOWN)
                    ++filescroll;
            }
        }
        else{
            if(!any_key_pressed())
                inputpause = 0;
            else
                inputpause--;
        }
    }

    for(i = 0; i < num_files; i++)
        free(filenames[i]);
    chdir("/documents/");
    return 1;
}