'use strict';

/*@
Ox.DocPanel <f> Documentation Panel
    () ->              <f> Documentation Panel
    (options) ->       <f> Documentation Panel
    (options, self) -> <f> Documentation Panel
    options <o> Options object
            collapsible <b|true> can be collabsed
            files <a|[]> files to parse for docs
            getModule <f> returns module for given item
            getSection <f> returns section for given item
            path <s|''> path prefix
            replace <[[]]|[]> See Ox.SyntaxHighlighter
            resizable <b|true> is resizable
            resize <a|[128, 256, 384]> resize positions
            size <s|256> default size
    self <o> shared private variable
    load <!> fired once all docs are loaded
@*/

Ox.DocPanel = function(options, self) {

    // FIXME: defaults should be falsy

    self = self || {};
    var that = Ox.Element({}, self)
        .defaults({
            collapsible: true,
            files: [],
            getModule: function(item) {
                return item.file.replace(self.options.path, '');
            },
            getSection: function(item) {
                return item.section;
            },
            path: '',
            replace: [],
            resizable: true,
            resize: [128, 256, 384],
            size: 256
        })
        .options(options || {});

    self.$list = Ox.Element();
    self.$page = Ox.Element();

    that.$element = Ox.SplitPanel({
        elements: [
            {
                collapsible: self.options.collapsible,
                element: self.$list,
                resizable: self.options.resizable,
                resize: self.options.resize,
                size: self.options.size
            },
            {
                element: self.$page
            }
        ],
        orientation: 'horizontal'
    });

    loadList(function(docItems) {
        self.items = docItems;
        that.triggerEvent('load', {});
    });

    function loadList(callback) {

        var counter = 0,
            docItems = [],
            length = self.options.files.length;

        self.options.files.forEach(function(file) {
            Ox.doc(self.options.path + file, function(fileItems) {
                docItems = Ox.merge(docItems, fileItems);
                if (++counter == length) {
                    makeTree(docItems);
                    callback(docItems);
                }
            });
        });

        function makeTree(docItems) {
            var treeItems = [];
            docItems.forEach(function(docItem) {
                var moduleIndex, sectionIndex;
                docItem.module = self.options.getModule(docItem);
                moduleIndex = Ox.getIndexById(treeItems, '_' + docItem.module);
                if (moduleIndex == -1) {
                    treeItems.push({
                        id: '_' + docItem.module,
                        items: [],
                        title: docItem.module
                    });
                    moduleIndex = treeItems.length - 1;
                }
                docItem.section = self.options.getSection(docItem);
                if (docItem.section) {
                    sectionIndex = Ox.getIndexById(
                        treeItems[moduleIndex].items,
                        '_' + docItem.module + '_' + docItem.section
                    );
                    if (sectionIndex == -1) {
                        treeItems[moduleIndex].items.push({
                            id: '_' + docItem.module + '_' + docItem.section,
                            items: [],
                            title: docItem.section
                        });
                        sectionIndex = treeItems[moduleIndex].items.length - 1;
                    }
                }
                (
                    docItem.section
                    ? treeItems[moduleIndex].items[sectionIndex]
                    : treeItems[moduleIndex]
                ).items.push({
                    id: docItem.name,
                    title: docItem.name
                });
            });
            treeItems.sort(sortByTitle);
            treeItems.forEach(function(item) {
                item.items.sort(sortByTitle);
                item.items.forEach(function(subitem) {
                    subitem.items.sort(sortByTitle);
                });
            });
            self.$list = Ox.TreeList({
                    items: treeItems,
                    width: self.options.size - Ox.UI.SCROLLBAR_SIZE
                })
                .bindEvent({
                    select: selectItem
                });
            // fixme
            /*
            var $foo = Ox.Container();
            self.$list.appendTo($foo);
            that.$element.replaceElement(0, $foo);
            */
            that.$element.replaceElement(0, self.$list);
        }

    }

    function getItemByName(name) {
        var item = {};
        Ox.forEach(self.items, function(v) {
            if (v.name == name) {
                item = v;
                return false;
            }
        });
        return item;
    }

    function selectItem(data) {
        var selected;
        if (data.ids.length) {
            selected = data.ids[0];
            if (selected[0] != '_') {
                self.$page = Ox.DocPage({
                    item: getItemByName(selected),
                    replace: self.options.replace
                });
                that.$element.replaceElement(1, self.$page);
                that.triggerEvent('select', {
                    id: selected
                });
            }
        }
    }

    function sortByTitle(a, b) {
        var ret = 0;
        if (a.title < b.title) {
            ret = -1;
        } else if (a.title > b.title) {
            ret = 1;
        }
        return ret;
    }
    /*@
    selectItem <f> select item
        (id) -> <u>  select an item
        id  <s> if of item to select
    @*/
    that.selectItem = function(id) {
        self.$list.triggerEvent('select', {'ids': [id]});
    };
    return that;

};