#include "fcb_inc_prot"

//==========================================/
//general
//==========================================/

//==========================================/
string c_hdr1(string s)
//==========================================/
    {
    return set_string_color(s, 0, 260, 260);
    }

//==========================================/
string c_hdr2(string s)
//==========================================/
    {
    return set_string_color(s, 260, 0, 80);
    }

//==========================================/
string c_hlt1(string s)
//==========================================/
    {
    return set_string_color(s, 160, 160, 160);
    }

//==========================================/
string c_hlt2(string s)
//==========================================/
    {
    return set_string_color(s, 30, 230, 30);
    }

//==========================================/
string c_hid(string s)
//==========================================/
    {
    return set_string_color(s, 60, 60, 60);
    }

//==========================================/
string c_sel(string s)
//==========================================/
    {
    return set_string_color(s, 260, 260, 260);
    }

//==========================================/
string c_fld(string s)
//==========================================/
    {
    return set_string_color(s, 200, 200, 260);
    }

//==========================================/
string c_crs(string s)
//==========================================/
    {
    return set_string_color(s, 200, 40, 40);
    }

//==========================================/
string get_color_string_val(int cval)
//==========================================/
    {
    string color_header_val = GetLocalString(FCB_HOST, COLOR_STRING_CACHE_ + IntToHexString(cval));
    if(color_header_val == "")
        {
        color_header_val = GetSubString(GetLocalString(FCB_HOST, COLOR_STRING), cval, 1);
        }

    return color_header_val;
    }

//==========================================/
string set_string_color(string s, int rval, int gval, int bval)
//==========================================/
    {
    rval = rval*(COLOR_STRING_LEN - 1)/COLOR_VAL_MAX;
    gval = gval*(COLOR_STRING_LEN - 1)/COLOR_VAL_MAX;
    bval = bval*(COLOR_STRING_LEN - 1)/COLOR_VAL_MAX;

    string result = "<c";
    string color_string = GetLocalString(FCB_HOST, COLOR_STRING);

    //----------------------------------------//
    string color_header_rval = GetLocalString(FCB_HOST, COLOR_STRING_CACHE_ + IntToHexString(rval));
    if(color_header_rval == "")
        {
        color_header_rval = GetSubString(color_string, rval, 1);

        SetLocalString(FCB_HOST, COLOR_STRING_CACHE_ + IntToHexString(rval), color_header_rval);
        }
    result += color_header_rval;

    //----------------------------------------//
    string color_header_gval = "";
    if(gval == rval)
        {
        result += color_header_rval;
        }
    else
        {
        color_header_gval = GetLocalString(FCB_HOST, COLOR_STRING_CACHE_ + IntToHexString(gval));
        if(color_header_gval == "")
            {
            color_header_gval = GetSubString(color_string, gval, 1);

            SetLocalString(FCB_HOST, COLOR_STRING_CACHE_ + IntToHexString(gval), color_header_gval);
            }
        result += color_header_gval;
        }

    //----------------------------------------//
    if(bval == rval)
        {
        result += color_header_rval;
        }
    else if(bval == gval)
        {
        result += color_header_gval;
        }
    else
        {
        string color_header_bval = GetLocalString(FCB_HOST, COLOR_STRING_CACHE_ + IntToHexString(bval));
        if(color_header_bval == "")
            {
            color_header_bval = GetSubString(color_string, bval, 1);

            SetLocalString(FCB_HOST, COLOR_STRING_CACHE_ + IntToHexString(bval), color_header_bval);
            }
        result += color_header_bval;
        }

    return (result + ">" + s + COLOR_TAG_END);
    }

//==========================================/
string set_gradation(string name, int r1, int g1, int b1, int r2, int g2, int b2)
//==========================================/
    {
    string result = "";
    int name_len = GetStringLength(name);

    int dr = (r2 - r1)/name_len;
    int dg = (g2 - g1)/name_len;
    int db = (b2 - b1)/name_len;

    int m = 0;
    while(m < name_len)
        {
        result += set_string_color(GetSubString(name, m, 1), r1, g1, b1);

        r1 += dr;
        g1 += dg;
        b1 += db;

        m++;
        }

    return result;
    }

//==========================================/
string ui_refresh_scroll_up(int condition)
//==========================================/
    {
    string disp = UI_TXT_UP;
    if(!condition)
        {
        disp = c_hid(disp);
        }

    return disp;
    }

//==========================================/
string ui_refresh_scroll_down(int condition)
//==========================================/
    {
    string disp = UI_TXT_DOWN;
    if(!condition)
        {
        disp = c_hid(disp);
        }

    return disp + UI_TXT_INDENT2;
    }

//==========================================/
//main related
//==========================================/

//==========================================/
void ui_main_initialize(int folder_index)
//==========================================/
    {
    //--------------------------------------/
    ui_disp_initialize();

    //--------------------------------------/
    //set initial stack name
    SetLocalString(FCB_HOST, STACK_NAME_ + IntToHexString(UI_STACK_DEFAULT_OFFSET), UI_TXT_STACK_ROOT);

    //[offset: 10][index: 10][select: 10]
    //set stack state to 1, 1, 1
    SetLocalInt(FCB_HOST, STACK_STATE, (UI_STACK_DEFAULT_OFFSET << BITLEN_FILE_2) | INCR_F10 | UI_STACK_DEFAULT_SEL);
    //ui_stack_refresh(UI_STACK_DEFAULT_OFFSET, 1, UI_STACK_DEFAULT_SEL);

    //--------------------------------------/
    //main refresh at folder index, 1, 0
    ui_main_refresh(folder_index | UI_MAIN_DEFAULT_OFFSET, folder_index | UI_MAIN_DEFAULT_SEL);
    //[...][offset: 10][folder_index: 10][selected: 10]
    //store it to stack
    int stack_param = (UI_MAIN_DEFAULT_OFFSET << BITLEN_FILE_2) | folder_index | UI_MAIN_DEFAULT_SEL;
    SetLocalInt(FCB_HOST, STACK_PARAM_ + IntToHexString(UI_STACK_DEFAULT_OFFSET), stack_param);
    }

//==========================================/
void ui_main_refresh_index(int file_dir, int file_dir_sel, int token_index)
//==========================================/
    {
    string file_name = GetLocalString(FCB_HOST, MAIN_FILE_NAME_ + IntToHexString(file_dir));
    int file_type = GetLocalInt(FCB_HOST, MAIN_FILE_TYPE_ + IntToHexString(file_dir));

    int color_sel = GetLocalInt(FCB_HOST, MAIN_FILE_NAME_COLOR_ + IntToHexString(file_dir));

    //hidden
    if(INCR_HIDDEN & file_type)
        {
        if(INCR_LINK & file_type)
            {
            file_name = c_hid(UI_TXT_LINK_PREFIX + file_name);
            }
        else
            {
            file_name = c_hid(file_name);
            }
        }

    //selected
    else if(file_dir == file_dir_sel)
        {
        if(INCR_LINK & file_type)
            {
            file_name = c_sel(UI_TXT_LINK_PREFIX + file_name);
            }
        else
            {
            file_name = c_sel(file_name);
            }
        }

    else if(INCR_D1000 & color_sel)
        {
        int rval = FILTER_D1 & (color_sel >>> BITLEN_COLOR_2);
        int gval = FILTER_D1 & (color_sel >>> BITLEN_COLOR_1);
        int bval = FILTER_D1 & color_sel;

        file_name = set_string_color(file_name, rval, gval, bval);

        if(INCR_LINK & file_type)
            {
            file_name = UI_TXT_LINK_PREFIX + file_name;
            }
        }

    //link
    else if(INCR_LINK & file_type)
        {
        file_name = UI_TXT_LINK_PREFIX + c_fld(file_name);
        }

    SetCustomToken(UI_TOKEN_MAIN + token_index, file_name);
    }

//==========================================/
void ui_main_refresh(int file_dir_offset, int file_dir_sel)
//==========================================/
    {
    //file_dir: [...][folder_index: 10][file_index: 10]
    //--------------------------------------/
    int n = 0;

    //folder index is 0
    if((FILTER_F10 & file_dir_offset) > 0)
        {
        //file_index: [...][folder_index: 10][file_index: 10]
        int file_index = GetLocalInt(FCB_HOST, MAIN_FILE_INDEX_ + IntToHexString(FILTER_F10 & file_dir_offset));

        while((file_dir_offset + n) <= file_index && n <= UI_MAIN_LIST_SIZE)
            {
            ui_main_refresh_index(file_dir_offset + n, file_dir_sel, n);

            n++;
            }

        //--------------------------------------/
        SetCustomToken(UI_TOKEN_MAIN + UI_MAIN_LIST_SIZE, ui_refresh_scroll_down((file_dir_offset + UI_MAIN_LIST_SIZE) <= file_index));

        //--------------------------------------/
        SetCustomToken(UI_TOKEN_MAIN + UI_MAIN_LIST_SIZE + 1, ui_refresh_scroll_up((FILTER_F1 & file_dir_offset) > UI_MAIN_DEFAULT_OFFSET));
        }
    SetLocalInt(FCB_HOST, UI_MAIN_LIST_LEN, n);
    }

//==========================================/
void ui_main_select(int n)
//==========================================/
    {
    //current stack index
    //[offset: 10][index: 10][select: 10]
    int stack_state = GetLocalInt(FCB_HOST, STACK_STATE);
    int stack_index_offset = stack_state >>> BITLEN_FILE_2;
    int stack_index_sel = FILTER_F1 & stack_state;

    //[...][offset: 10][folder_index: 10][selected: 10]
    int stack_param = GetLocalInt(FCB_HOST, STACK_PARAM_ + IntToHexString(stack_index_sel));

    //[folder_index: 10][offset: 10]
    int file_dir_offset = (FILTER_F10 & stack_param) | (stack_param >>> BITLEN_FILE_2);

    int file_type = GetLocalInt(FCB_HOST, MAIN_FILE_TYPE_ + IntToHexString(file_dir_offset + n));

    //if not in hidden mode
    //--------------------------------------/
    if(INCR_HIDDEN & (~file_type))
        {
        //[folder_index: 10][selected: 10]
        int file_dir_sel = FILTER_F11 & stack_param;

        //selected different file...
        if((file_dir_offset + n) != file_dir_sel)
            {
            //update selection selection
            //[offset: 10][folder_index: 10][offset+n: 10]
            SetLocalInt(FCB_HOST, STACK_PARAM_ + IntToHexString(stack_index_sel), (FILTER_F100 & stack_param) | (file_dir_offset + n));
            }

        //--------------------------------------/
        SetLocalInt(FCB_HOST, SCRIPT_PARAM, (FILTER_F100 & file_type) | stack_index_sel);

        //if link type
        //--------------------------------------/
        if(INCR_LINK & file_type)
            {
            int folder_index = FILTER_F10 & file_type;
            ui_main_refresh(folder_index | UI_MAIN_DEFAULT_OFFSET, folder_index | UI_MAIN_DEFAULT_SEL);

            int stack_index_sel_new = stack_index_sel+1;

            //stack: [...][offset: 10][folder_index: 10][selected: 10]
            SetLocalInt(FCB_HOST, STACK_PARAM_ + IntToHexString(stack_index_sel_new), (UI_MAIN_DEFAULT_OFFSET << BITLEN_FILE_2) | folder_index | UI_MAIN_DEFAULT_SEL);

            string file_name = GetLocalString(FCB_HOST, MAIN_FILE_NAME_+  IntToHexString(file_dir_offset + n));
            SetLocalString(FCB_HOST, STACK_NAME_ + IntToHexString(stack_index_sel_new), file_name);

            //[offset: 10][index: 10][select: 10]
            SetLocalInt(FCB_HOST, STACK_STATE, (FILTER_F100 & stack_state) | (stack_index_sel_new << BITLEN_FILE_1) | stack_index_sel_new);
            //ui_stack_refresh(stack_state >>> BITLEN_FILE_2, stack_index_sel_new, stack_index_sel_new);

            //misc
            //--------------------------------------/
            //ui_disp_clear_local();
            }
        else
            {
            //selected different file...
            if((file_dir_offset + n) != file_dir_sel)
                {
                //redraw file_dir_offset + n
                ui_main_refresh_index(file_dir_offset + n, file_dir_offset + n, n);

                //old selection in visual range
                if(file_dir_sel >= file_dir_offset && file_dir_sel < (file_dir_offset + UI_MAIN_LIST_SIZE))
                    {
                    //redraw file_dir_sel
                    ui_main_refresh_index(file_dir_sel, file_dir_offset + n, file_dir_sel - file_dir_offset);
                    }
                }
            }

        ExecuteScript(FCB_SCRIPT_PREFIX + SCRIPT_MAIN_OPTION_HANDLER, FCB_HOST);
        ui_disp_refresh_txt();
        }
    }

//==========================================/
void ui_main_scroll_down()
//==========================================/
    {
    //current stack index
    //[offset: 10][index: 10][select: 10]
    int stack_index_sel = FILTER_F1 & GetLocalInt(FCB_HOST, STACK_STATE);

    //[...][offset: 10][folder_index: 10][selected: 10]
    int stack_param = GetLocalInt(FCB_HOST, STACK_PARAM_ + IntToHexString(stack_index_sel));

    int stack_index_offset = stack_param >>> BITLEN_FILE_2;
    int file_index = GetLocalInt(FCB_HOST, MAIN_FILE_INDEX_ + IntToHexString(FILTER_F10 & stack_param));
    //if offset < file_index
    if((FILTER_F1 & file_index) >= (stack_index_offset + UI_MAIN_LIST_SIZE))
        {
        //stack: [...][offset: 10][folder_index: 10][selected: 10]
        SetLocalInt(FCB_HOST, STACK_PARAM_ + IntToHexString(stack_index_sel), stack_param + (UI_MAIN_SCROLL_INCR << BITLEN_FILE_2));
        ui_main_refresh((FILTER_F10 & stack_param) | (stack_index_offset + UI_MAIN_SCROLL_INCR), FILTER_F11 & stack_param);
        }
    }

//==========================================/
void ui_main_scroll_up()
//==========================================/
    {
    //current stack index
    //[offset: 10][index: 10][select: 10]
    int stack_index_sel = FILTER_F1 & GetLocalInt(FCB_HOST, STACK_STATE);

    //[...][offset: 10][folder_index: 10][selected: 10]
    int stack_param = GetLocalInt(FCB_HOST, STACK_PARAM_ + IntToHexString(stack_index_sel));

    int stack_index_offset = stack_param >>> BITLEN_FILE_2;
    if(stack_index_offset > UI_MAIN_DEFAULT_OFFSET)
        {
        //stack: [...][offset: 10][folder_index: 10][selected: 10]
        SetLocalInt(FCB_HOST, STACK_PARAM_ + IntToHexString(stack_index_sel), stack_param - (UI_MAIN_SCROLL_INCR << BITLEN_FILE_2));
        ui_main_refresh((FILTER_F10 & stack_param) | (stack_index_offset - UI_MAIN_SCROLL_INCR), FILTER_F11 & stack_param);
        }
    }

//==========================================/
void ui_main_set_hidden(int file_dir, int hidden)
//==========================================/
    {
    if(hidden)
        {
        int file_type = GetLocalInt(FCB_HOST, MAIN_FILE_TYPE_ + IntToHexString(file_dir));
        SetLocalInt(FCB_HOST, MAIN_FILE_TYPE_ + IntToHexString(file_dir), INCR_HIDDEN | file_type);
        }
    else
        {
        int file_type = GetLocalInt(FCB_HOST, MAIN_FILE_TYPE_ + IntToHexString(file_dir));
        SetLocalInt(FCB_HOST, MAIN_FILE_TYPE_ + IntToHexString(file_dir), (~INCR_HIDDEN) & file_type);
        }
    }

//==========================================/
void ui_main_set_hidden_refresh(int file_dir, int hidden)
//==========================================/
    {
    int stack_state = GetLocalInt(FCB_HOST, STACK_STATE);
    //[...][offset: 10][folder_index: 10][selected: 10]
    int stack_param = GetLocalInt(FCB_HOST, STACK_PARAM_ + IntToHexString(FILTER_F1 & stack_state));

    if(hidden)
        {
        int file_type = GetLocalInt(FCB_HOST, MAIN_FILE_TYPE_ + IntToHexString(file_dir));
        SetLocalInt(FCB_HOST, MAIN_FILE_TYPE_ + IntToHexString(file_dir), INCR_HIDDEN | file_type);

        if((FILTER_F10 & file_dir) == (FILTER_F10 & stack_param))
            {
            int file_dir_offset = (FILTER_F10 & stack_param) | (stack_param >>> BITLEN_FILE_2);

            if(file_dir >= file_dir_offset && file_dir <= (file_dir_offset + UI_MAIN_LIST_SIZE))
                {
                int file_dir_sel = FILTER_F11 & stack_param;

                if(file_dir == file_dir_sel)
                    {
                    SetLocalInt(FCB_HOST, STACK_PARAM_ + IntToHexString(FILTER_F1 & stack_state), FILTER_F110 & stack_param);
                    ui_main_refresh_index(file_dir, 0, file_dir_sel - file_dir_offset);
                    }
                else
                    {
                    ui_main_refresh_index(file_dir, file_dir_sel, file_dir - file_dir_offset);
                    }
                }
            }
        }
    else
        {
        int file_type = GetLocalInt(FCB_HOST, MAIN_FILE_TYPE_ + IntToHexString(file_dir));
        SetLocalInt(FCB_HOST, MAIN_FILE_TYPE_ + IntToHexString(file_dir), (~INCR_HIDDEN) & file_type);

        if((FILTER_F10 & file_dir) == (FILTER_F10 & stack_param))
            {
            int file_dir_offset = (FILTER_F10 & stack_param) | (stack_param >>> BITLEN_FILE_2);

            if(file_dir >= file_dir_offset && file_dir <= (file_dir_offset + UI_MAIN_LIST_SIZE))
                {
                int file_dir_sel = FILTER_F11 & stack_param;
                ui_main_refresh_index(file_dir, file_dir_sel, file_dir - file_dir_offset);
                }
            }
        }
    }

//==========================================/
void remove_main_file_dir(int file_dir, int token_index)
//==========================================/
    {
    ui_main_set_hidden(file_dir, 1);
    ui_main_refresh_index(file_dir, 0, token_index);
    }

//==========================================/
void clear_main_folder(int file_dir)
//==========================================/
    {
    SetLocalInt(FCB_HOST, MAIN_FILE_INDEX_ + IntToHexString(FILTER_F10 & file_dir), file_dir);
    }

//==========================================/
void set_main_file_name_color(int file_dir, int rval, int gval, int bval)
//==========================================/
    {
    if(rval > COLOR_VAL_MAX)
        {
        rval = COLOR_VAL_MAX;
        }

    if(gval > COLOR_VAL_MAX)
        {
        gval = COLOR_VAL_MAX;
        }

    if(bval > COLOR_VAL_MAX)
        {
        bval = COLOR_VAL_MAX;
        }

    SetLocalInt(FCB_HOST, MAIN_FILE_NAME_COLOR_ + IntToHexString(file_dir), INCR_D1000 | (rval << BITLEN_COLOR_2) | (gval << BITLEN_COLOR_1) | bval);
    }

//==========================================/
void clear_main_file_name_color(int file_dir)
//==========================================/
    {
    DeleteLocalInt(FCB_HOST, MAIN_FILE_NAME_COLOR_ + IntToHexString(file_dir));
    }

//==========================================/
//stack related
//==========================================/

//==========================================/
void ui_stack_back()
//==========================================/
    {
    //[offset: 10][index: 10][select: 10]
    int stack_state = GetLocalInt(FCB_HOST, STACK_STATE);
    int stack_index_sel = FILTER_F1 & stack_state;
    //int stack_index_offset = stack_state >>> BITLEN_FILE_2;

    //selected different file...
    SetLocalInt(FCB_HOST, STACK_STATE, (FILTER_F110 & stack_state) | (stack_index_sel - 1));

    //stack: [...][offset: 10][folder_index: 10][selected: 10]
    int stack_param = GetLocalInt(FCB_HOST, STACK_PARAM_ + IntToHexString(stack_index_sel - 1));

    ui_main_refresh((FILTER_F10 & stack_param) | (stack_param >>> BITLEN_FILE_2), FILTER_F11 & stack_param);

    //misc
    //--------------------------------------/
    ui_disp_clear_local();
    ui_disp_refresh_txt();
    }

//==========================================/
void ui_stack_index(int index)
//==========================================/
    {
    //[offset: 10][index: 10][select: 10]
    int stack_state = GetLocalInt(FCB_HOST, STACK_STATE);
    //int stack_index_sel = FILTER_F1 & stack_state;
    //int stack_index_offset = stack_state >>> BITLEN_FILE_2;

    //selected different file...
    SetLocalInt(FCB_HOST, STACK_STATE, (FILTER_F110 & stack_state) | UI_STACK_DEFAULT_OFFSET + index);

    //stack: [...][offset: 10][folder_index: 10][selected: 10]
    int stack_param = GetLocalInt(FCB_HOST, STACK_PARAM_ + IntToHexString(UI_STACK_DEFAULT_OFFSET + index));

    ui_main_refresh((FILTER_F10 & stack_param) | (stack_param >>> BITLEN_FILE_2), FILTER_F11 & stack_param);

    //misc
    //--------------------------------------/
    ui_disp_clear_local();
    ui_disp_refresh_txt();
    }

//==========================================/
//resp
//==========================================/

//==========================================/
void ui_disp_initialize()
//==========================================/
    {
    int n = 0;
    while(n <= DISP_INDEX_POS)
        {
        ui_disp_state_new(n, 0);
        ui_disp_set_txt(n, "", "");

        n++;
        }
    }

//==========================================/
void ui_disp_refresh_txt()
//==========================================/
    {
    int disp_state = GetLocalInt(FCB_HOST, DISP_STATE);

    int n = 0;
    int token_index = 0;
    int index_pos = 1;

    while(n <= DISP_INDEX_POS)
        {
        if(disp_state & index_pos)
            {
            string disp = GetLocalString(FCB_HOST, UI_DISP_TXT_ + IntToHexString(n));

            disp_state &= ~index_pos;
            if(disp != "")
                {
                if(disp_state > index_pos)
                    {
                    disp += UI_TXT_INDENT;
                    }

                SetCustomToken(UI_TOKEN_DISP + token_index, disp);
                token_index++;
                }
            }

        index_pos <<= 1;
        n++;
        }

    while(token_index < DISP_LIST_SIZE)
        {
        SetCustomToken(UI_TOKEN_DISP + token_index, "");

        token_index++;
        }
    }

//==========================================/
void ui_disp_state_new(int n, int disp)
//==========================================/
    {
    if(disp)
        {
        SetLocalInt(FCB_HOST, DISP_STATE,  GetLocalInt(FCB_HOST, DISP_STATE) | (1 << n));
        }
    else
        {
        SetLocalInt(FCB_HOST, DISP_STATE,  GetLocalInt(FCB_HOST, DISP_STATE) & ~(1 << n));
        }
    }

//==========================================/
void ui_disp_set_txt(int n, string hdr, string txt = "")
//==========================================/
    {
    string disp = "";
    if(hdr != "")
        {
        disp += c_hdr1(hdr);

        if(txt != "")
            {
            disp += UI_TXT_INDENT + txt;
            }
        }

    else if(txt != "")
        {
        disp += txt;
        }

    SetLocalString(FCB_HOST, UI_DISP_TXT_ + IntToHexString(n), disp);
    }

//==========================================/
void ui_disp_clear_local()
//==========================================/
    {
    ui_disp_state_new(DISP_INDEX_LOCAL1, 0);
    }

//==========================================/
void ui_set_active_disp_index(int disp_index1 = -1, int disp_index2 = -1)
//==========================================/
    {
    if(disp_index1 > -1)
        {
        ui_disp_state_new(disp_index1, 1);
        }
    else
        {
        ui_disp_state_new(disp_index1, 0);
        }

    if(disp_index2 > -1)
        {
        ui_disp_state_new(disp_index2, 1);
        }
    else
        {
        ui_disp_state_new(disp_index2, 0);
        }

    int n = 0;
    while(n <= DISP_INDEX_POS)
        {
        if(n != disp_index1)
            {
            if(n != disp_index2)
                {
                ui_disp_state_new(n, 0);
                }
            }
        n++;
        }
    }
