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

/*@
Ox.Select <f:Ox.Element> Select Object
    () ->              <f> Select Object
    (options) ->       <f> Select Object
    (options, self) -> <f> Select Object
    options <o> Options object
        id <s> element id
        items <a|[]> items
        label <s|''> Label
        labelWidth <n|64> Label width
        max <n|1> minimum number of selected items
        min <n|1> maximum number of selected items
        overlap <s|'none'> can be none, left or right
        selectable <b|true> is selectable
        size <s|'medium'> size, can be small, medium, large
        title <s|''> select title
        type <s|'text'> can be 'text' or 'image'
        width <s|n|'auto'> can be auto or width in pixels
    self    <o> shared private variable
    click <!> on click event
    change <!> on change event
@*/

Ox.Select = function(options, self) {

    // fixme: make selected a separate option
    // fixme: selected item needs attribute "checked", not "selected" ... that's strange
    self = self || {};
    var that = Ox.Element({
                tooltip: options.tooltip || ''
            }, self)
            .defaults({
                id: '',
                items: [],
                label: '',
                labelWidth: 64,
                max: 1,
                min: 1,
                overlap: 'none', // can be none, left or right
                selectable: true,
                size: 'medium',
                title: '',
                type: 'text', // can be 'text' or 'image'
                value: '',
                width: 'auto'
            })
            // fixme: make default selection restorable
            // or allow for extra action items below options
            // fixme: passing value has no effect
            .options(options)
            .addClass(
                'OxSelect Ox' + Ox.toTitleCase(self.options.size) + (
                    self.options.overlap == 'none'
                    ? '' : ' OxOverlap' + Ox.toTitleCase(self.options.overlap)
                ) + (self.options.label ? ' OxLabelSelect' : '')
            )
            .css(self.options.width == 'auto' ? {} : {
                width: self.options.width - 2 + 'px'
            })
            .bindEvent({
                key_escape: loseFocus,
                key_down: showMenu
            });

    //Ox.Log('Form', 'Ox.Select', self.options);

    Ox.extend(self, {
        buttonId: self.options.id + 'Button',
        groupId: self.options.id + 'Group',
        menuId: self.options.id + 'Menu'
    });

    if (self.options.selectable) {
        self.optionGroup = new Ox.OptionGroup(
            self.options.items,
            self.options.min,
            self.options.max
        );
        self.options.items = self.optionGroup.init();
        self.checked = self.optionGroup.checked();
    }

    if (self.options.label) {
        self.$label = Ox.Label({
            overlap: 'right',
            textAlign: 'right',
            title: self.options.label,
            width: self.options.labelWidth
        })
        .click(function() {
            // fixme: ???
            // that.focus();
        })
        .appendTo(that);
    }

    if (self.options.type == 'text') {
        self.$title = $('<div>')
            .addClass('OxTitle')
            .css({
                // fixme: used to be 22. obscure
                width: (self.options.width - 24 - (
                    self.options.label ? self.options.labelWidth : 0
                )) + 'px'
            })
            .html(
                self.options.title ? self.options.title
                : self.options.items[self.checked[0]].title
            )
            .click(showMenu)
            .appendTo(that.$element);
    }

    self.$button = Ox.Button({
            id: self.buttonId,
            style: 'symbol',
            title: 'select',
            type: 'image'
        })
        .bindEvent('click', showMenu)
        .appendTo(that);

    self.$menu = Ox.Menu({
            element: self.$title || self.$button,
            id: self.menuId,
            items: [self.options.selectable ? {
                group: self.groupId,
                items: self.options.items,
                max: self.options.max,
                min: self.options.min
            } : self.options.items],
            side: 'bottom',
            size: self.options.size
        })
        .bindEvent({
            change: changeMenu,
            click: clickMenu,
            hide: hideMenu
        });

    self.options.type == 'image' && self.$menu.addClass('OxRight');

    function clickMenu(data) {
        that.triggerEvent('click', data);
    }

    function changeMenu(data) {
        //Ox.Log('Form', 'clickMenu: ', self.options.id, data)
        if (self.options.selectable) {
            self.checked = self.optionGroup.checked();
            self.options.value = data.checked[0].id;
            self.$title && self.$title.html(
                self.options.title ? self.options.title : data.checked[0].title
            );
            that.triggerEvent('change', {
                selected: data.checked
            });
        } else {
            that.triggerEvent('click', data);
        }
    }

    function hideMenu() {
        //Ox.Log('Form', '%% hideMenu that', that, 'self', self)
        that.removeClass('OxSelected');
        // self.$button.removeClass('OxSelected');
        //Ox.Log('Form', '%% hideMenu end')
    }

    function loseFocus() {
        that.loseFocus();
    }

    function showMenu() {
        that.gainFocus();
        that.addClass('OxSelected');
        self.options.tooltip && that.$tooltip.hide();
        self.$menu.showMenu();
    }

    self.setOption = function(key, value) {
        if (key == 'value') {
            Ox.Log('Form', 'SETTING VALUE OPTION', value)
            that.selectItem(value);
        }
    };

    that.disableItem = function(id) {
        self.$menu.getItem(id).options({disabled: true});
    };

    that.enableItem = function(id) {
        self.$menu.getItem(id).options({disabled: false});
    };

    // FIXME: selected() _and_ selectItem() _and_ value() ???

    /*@
    selected <f> gets selected item
        () -> <o> returns object of selected items with id, title
    @*/
    that.selected = function() {
        return /*self.checked*/self.optionGroup.checked().map(function(v) {
            return {
                id: self.options.items[v].id,
                title: self.options.items[v].title
            };
        });
    };

    /*@
    selectItem <f> select item in group
        (id) -> <u> select item by id
        id <s> item id
    @*/
    that.selectItem = function(id) {
        Ox.Log('Form', 'selectItem', id, self.options.items, self.options.items.length, Ox.getObjectById(self.options.items, id))
        self.options.type == 'text' && self.$title.html(
            Ox.getObjectById(self.options.items, id).title
        );
        self.$menu.checkItem(id);
        self.checked = self.optionGroup.checked();
    };

    /*
    that.width = function(val) {
        // fixme: silly hack, and won't work for css() ... remove!
        that.$element.width(val + 16);
        that.$button.width(val);
        //that.$symbol.width(val);
        return that;
    };
    */

    that.value = function() {
        if (arguments.length == 0) {
            //Ox.Log('Form', 'selected::', that.selected())
            return that.selected()[0].id;
        } else {
            that.selectItem(arguments[0]);
            return that;
            /*
            Ox.Log('Form', 'ELSE');
            that.selectItem(arguments[0]);
            return that;
            */
        }
    };

    return that;

};
