// vim: et:ts=4:sw=4:sts=4:ft=javascript
'use strict';
/*@
Ox.ColorPicker <f:Ox.Element> ColorPicker Element
    () ->              <f> ColorPicker Element
    (options) ->       <f> ColorPicker Element
    (options, self) -> <f> ColorPicker Element
    options <o> Options object
        id <s> element id
        value <s|0, 0, 0> rgb value
    self <o>    Shared private variable
    change <!> triggered on change of value
@*/

Ox.ColorPicker = function(options, self) {

    self = self || {};
    var that = Ox.Element({}, self)
            .defaults({
                id: '',
                mode: 'RGB',
                value: options.mode == 'HSL' ? [0, 1, 0.5] : [0, 0, 0]
            })
            .options(options || {});

    //Ox.Log('Form', self)
    self.$ranges = [];

    Ox.loop(3, function(i) {
        self.$ranges[i] = Ox.Range({
                arrows: true,
                changeOnDrag: true,
                id: self.options.id + i,
                max: self.options.mode == 'RGB' ? 255 : i == 0 ? 359 : 1,
                size: self.options.mode == 'RGB' ? 328 : 432, // 256|360 + 16 + 40 + 16
                step: self.options.mode == 'RGB' || i == 0 ? 1 : 0.01,
                thumbSize: 40,
                thumbValue: true,
                trackColors: getColors(i),
                trackGradient: true,
                value: self.options.value[i]
            })
            .css({
                position: 'absolute',
                top: (i * 15) + 'px'
            })
            .bindEvent({
                change: function(data) {
                    change(i, data.value);
                }
            })
            .appendTo(that);
        // fixme: make self.$ranges[i].children() work
        if (i == 0) {
            // fixme: this should go into Ox.UI.css
            self.$ranges[i].$element.children('input.OxOverlapRight').css({
                MozBorderRadius: 0,
                WebkitBorderRadius: 0
            });
            self.$ranges[i].$element.children('input.OxOverlapLeft').css({
                MozBorderRadius: '0 8px 0 0',
                WebkitBorderRadius: '0 8px 0 0'
            });
        } else {
            self.$ranges[i].$element.children('input').css({
                MozBorderRadius: 0,
                WebkitBorderRadius: 0
            });
        }
    });

    that = Ox.Picker({
        element: that,
        elementHeight: 46,
        elementWidth: self.options.mode == 'RGB' ? 328 : 432,
        id: self.options.id
    });

    function change(index, value) {
        self.options.value[index] = value;
        that.$label.css({
            background: 'rgb(' + getRGB(self.options.value).join(', ') + ')'
        });
        Ox.loop(3, function(i) {
            if (i != index) {
                self.$ranges[i].options({
                    trackColors: getColors(i)
                });
            }
        });
        that.triggerEvent('change', {
            value: self.options.value
        });
    }

    function getColors(index) {
        return (
            self.options.mode == 'RGB' ? [
                Ox.range(3).map(function(i) {
                    return i == index ? 0 : self.options.value[i];
                }),
                Ox.range(3).map(function(i) {
                    return i == index ? 255 : self.options.value[i];
                })
            ]
            : index == 0 ? Ox.range(7).map(function(i) {
                return [i * 60, self.options.value[1], self.options.value[2]];
            })
            : Ox.range(3).map(function(i) {
                return [
                    self.options.value[0],
                    index == 1 ? i / 2 : self.options.value[1],
                    index == 2 ? i / 2 : self.options.value[2]
                ];
            })
        ).map(function(values) {
            return 'rgb(' + getRGB(values).join(', ') + ')';
        });
    }

    function getRGB(values) {
        return self.options.mode == 'RGB'
            ? values
            : Ox.rgb(values).map(function(value) {
                return Math.round(value);
            });
    }

    return that;

};
