// vim: et:ts=4:sw=4:sts=4:ft=js

/*@
Ox.TreeList <f:Ox.Element> TreeList Object
    () ->              <f> TreeList Object
    (options) ->       <f> TreeList Object
    (options, self) -> <f> TreeList Object
    options <o> Options object
        data <f|null> data to be parsed to items, needs documentation
        items <a|[]> array of items
        max <n|-1> maximum number of items that can be selected, -1 unlimited
        min <n|0> minimum number of items that have to be selected
        selected <a|[]> selected ids
        width <n|256> list width
    self    <o> shared private variable
@*/

Ox.TreeList = function(options, self) {

    // fixme: expanding the last item should cause some scroll

    var self = self || {},
        that = new Ox.Element({}, self)
            .defaults({
                data: null,
                items: [],
                max: -1,
                min: 0,
                selected: [],
                width: 256
            })
            .options(options || {});

    if (self.options.data) {
        self.options.items = [];
        //Ox.print('d', self.options.data, 'i', self.options.items)
        Ox.forEach(self.options.data, function(value, key) {
            self.options.items.push(parseData(key, value));
        });
        //Ox.print('d', self.options.data, 'i', self.options.items)
    }

    that.$element = new Ox.List({
            construct: constructItem,
            itemHeight: 16,
            items: parseItems(),
            itemWidth: self.options.width,
            max: self.options.max,
            min: self.options.min,
            unique: 'id'
        }, $.extend({}, self))
        .addClass('OxTextList OxTreeList')
        .css({
            width: self.options.width + 'px'
        })
        .click(clickItem)
        .bindEvent({
            toggle: toggleItems
        });

    function clickItem(e) {
        var $target = $(e.target),
            $item, id, item;
        if ($target.is('.OxToggle')) {
            $item = $target.parent().parent();
            id = $item.data('id');
            item = getItemById(id);
            toggleItem(item, !item.expanded);
        }
    }

    function constructItem(data) {
        var $item = $('<div>'),
            padding = (data.level + !data.items) * 16 - 8;
        if (data.level || !data.items) {
            $('<div>')
                .addClass('OxCell OxTarget')
                .css({
                    width: padding + 'px',
                })
                .appendTo($item);
        }
        if (data.items) {
            $('<div>')
                .addClass('OxCell')
                .css({
                    width: '8px',
                })
                .append(
                    // fixme: need Ox.Icon()
                    $('<img>')
                        .addClass('OxToggle')
                        .attr({
                            src: Ox.UI.getImagePath(
                                'symbol' + (data.expanded ? 'Down' : 'Right') + '.svg'
                            )
                        })
                        .css({
                            width: '10px',
                            height: '10px',
                            padding: '3px'
                        })
                )
                .appendTo($item);
        }
        $('<div>')
            .addClass('OxCell OxTarget')
            .css({
                width: (self.options.width - padding - 32 + !data.items * 16) + 'px'
            })
            .html(data.title)
            .appendTo($item);
        return $item;
    }

    function getItemById(id, items, level) {
        var items = items || self.options.items,
            level = level || 0,
            ret = null;
        Ox.forEach(items, function(item) {
            if (item.id == id) {
                ret = $.extend(item, {
                    level: level
                });
                return false;
            }
            if (item.items) {
                ret = getItemById(id, item.items, level + 1);
                if (ret) {
                    return false;
                }
            }
        });
        return ret;
    }

    function parseData(key, value) {
        //Ox.print('parseData', key, value)
        var ret = {
                id: key,
                title: key.toString().split('.').pop()
            },
            type = Ox.typeOf(value);
        if (type == 'array' || type == 'object') {
            ret.title += ': ' + Ox.toTitleCase(Ox.typeOf(value));
            ret.items = Ox.map(Ox.sort(Ox.keys(value)), function(k) {
                return parseData(key + '.' + k, value[k]);
            });
        } else {
            ret.title += ': ' + (
                type == 'function' ?
                    value.toString().split('{')[0] :
                    JSON.stringify(value)
            )
        }
        return ret;
    }

    function parseItems(items, level) {
        var items = items || self.options.items,
            level = level || 0,
            ret = [];
        items.forEach(function(item, i) {
            var item_ = $.extend({
                    level: level
                }, item, item.items ? {
                    items: !!item.expanded ?
                        parseItems(item.items, level + 1) : []
                } : {});
            ret.push(item_);
            item.items && $.merge(ret, item_.items);
        });
        return ret;
    }

    function toggleItem(item, expanded) {
        var $img, pos;
        item.expanded = expanded;
        //getItemById(item.id).expanded = expanded;
        $.each(that.$element.find('.OxItem'), function(i, v) {
            var $item = $(v);
            if ($item.data('id') == item.id) {
                $img = $item.find('.OxToggle');
                pos = $item.data('position');
                return false;
            }
        });
        $img.attr({
            src: Ox.UI.getImagePath(
                'symbol' + (expanded ? 'Down' : 'Right') + '.svg'
            )
        });
        that.$element.value(item.id, 'expanded', expanded);
        expanded ?
            that.$element.addItems(pos + 1, parseItems(item.items, item.level + 1)) :
            that.$element.removeItems(pos + 1, parseItems(item.items, item.level + 1).length);
    }

    function toggleItems(event, data) {
        data.ids.forEach(function(id, i) {
            var item = getItemById(id);
            if (item.items && data.expanded != !!item.expanded) {
                toggleItem(item, data.expanded);
            }
        });
    }

    self.setOption = function(key, value) {
        if (key == 'data') {
            
        } else if (key == 'width') {

        }
    };

    return that;
    
};
