/*
 * Mr. 4th Dimention - Allen Webster
 *
 * 14.12.2019
 *
 * Documentation of the custom layer's primary api.
 *
 */

// TOP

function Doc_Cluster*
doc_commands(Arena *arena){
    Doc_Cluster *cluster = new_doc_cluster(arena, "Commands", "commands");
    for (i32 i = 0; i < ArrayCount(fcoder_metacmd_table); i += 1){
        String_Const_u8 cmd_name = SCu8(fcoder_metacmd_table[i].name,
                                                                fcoder_metacmd_table[i].name_len);
        String_Const_u8 title = push_u8_stringf(arena, "Command %.*s", string_expand(cmd_name));
        Doc_Page *page = new_doc_page(arena, cluster, (char*)title.str, (char*)cmd_name.str);
        Doc_Block *block = new_doc_block(arena, page, "brief");
        doc_text(arena, block, fcoder_metacmd_table[i].description);
    }
    return(cluster);
}

function Doc_Cluster*
doc_default_bindings(Arena *arena, Mapping *mapping, i64 global_id, i64 file_id, i64 code_id){
    Doc_Cluster *cluster = new_doc_cluster(arena, "Bindings", "bindings");
    
        Doc_Page *page = new_doc_page(arena, cluster, "Default Bindings", "default_bindings");
    for (Command_Map *map = mapping->first_map;
         map != 0;
         map = map->next){
        char *map_name = "";
        if (map->id == global_id){
            map_name = "Global";
        }
        else if (map->id == file_id){
            map_name = "File";
        }
        else if (map->id == code_id){
            map_name = "Code";
        }
        
        Doc_Block *block = new_doc_block(arena, page, map_name);
        Doc_Paragraph *par = new_doc_par_table(arena, block);
        
        struct Bind_Node{
            Bind_Node *next;
            Input_Event_Kind kind;
            u32 sub_code;
            Input_Modifier_Set mods;
            Command_Binding binding;
            u32 j;
        };
        
        Bind_Node *first = 0;
        Bind_Node *last = 0;
        i32 node_count = 0;
        
        if (map->text_input_command.name != 0){
            Bind_Node *node = push_array_zero(arena, Bind_Node, 1);
            sll_queue_push(first, last, node);
            node_count += 1;
            node->binding = map->text_input_command;
            node->j = max_u32;
        }
        
        u32 counts[] = {
            KeyCode_COUNT,
            KeyCode_COUNT,
            MouseCode_COUNT,
            MouseCode_COUNT,
            1,
            1,
            CoreCode_COUNT,
        };
        
        u32 event_codes[] = {
            InputEventKind_KeyStroke,
            InputEventKind_KeyRelease,
            InputEventKind_MouseButton,
            InputEventKind_MouseButtonRelease,
            InputEventKind_MouseWheel,
            InputEventKind_MouseMove,
            InputEventKind_Core,
        };
        
        char *mouse_wheel_name[] = {"MoveWheel"};
        char *mouse_move_name[] = {"MoveMove"};
        
        char **event_names[] = {
            key_code_name,
            key_code_name,
            mouse_code_name,
            mouse_code_name,
            mouse_wheel_name,
            mouse_move_name,
            core_code_name,
        };
        
        b32 is_release[] = {
            false,
            true,
            false,
            true,
            false,
            false,
            false,
        };
        
        for (u32 j = 0; j < ArrayCount(counts); j += 1){
            for (u32 code = 0; code < counts[j]; code += 1){
                u64 key = mapping__key(event_codes[j], code);
                Table_Lookup lookup = table_lookup(&map->event_code_to_binding_list, key);
                if (lookup.found_match){
                    u64 val = 0;
                    table_read(&map->event_code_to_binding_list, lookup, &val);
                    Command_Binding_List *list = (Command_Binding_List*)IntAsPtr(val);
                    for (SNode *snode = list->first;
                         snode != 0;
                         snode = snode->next){
                        Command_Modified_Binding *mod_binding = CastFromMember(Command_Modified_Binding, order_node, snode);
                        
                        Bind_Node *node = push_array_zero(arena, Bind_Node, 1);
                        sll_queue_push(first, last, node);
                        node_count += 1;
                        node->kind = event_codes[j];
                        node->sub_code = code;
                        node->mods = mod_binding->mods;
                        node->binding = mod_binding->binding;
                        node->j = j;
                    }
                }
            }
        }
        
        Vec2_i32 table_dims = V2i32(2, node_count);
        Doc_Content_List *vals = push_array_zero(arena, Doc_Content_List, table_dims.x*table_dims.y);
        Bind_Node *bnode = first;
        for (i32 y = 0; y < table_dims.y; y += 1, bnode = bnode->next){
            Doc_Content_List *line = &vals[y*table_dims.x];
            doc_text(arena, &line[0], "[");
            if (bnode->j != max_u32){
            doc_text(arena, &line[0], event_names[bnode->j][bnode->sub_code]);
            if (is_release[bnode->j]){
                doc_text(arena, &line[0], "Release");
                }
                
                Input_Modifier_Set *mods = &bnode->mods;
                for (i32 k = 0; k < mods->count; k += 1){
                    doc_text(arena, &line[0], key_code_name[mods->mods[k]]);
                }
            }
            else{
                doc_text(arena, &line[0], "TextInput");
            }
            doc_text(arena, &line[0], "]");
            
            Doc_Content *content = doc_text(arena, &line[1], bnode->binding.name);
            content->page_link = SCu8(bnode->binding.name);
        }
        
        par->table.dim = table_dims;
        par->table.vals = vals;
        }
    
    return(cluster);
}

// BOTTOM