/**
 * Sencha Pro Services presents xtype "colorselector".
 * API has been kept as close to the regular colorpicker as possible. The Selector can be
 * rendered to any container.
 *
 * The defaul selected color is configurable via {@link #value} config
 * and The Format is configurable via {@link #format}. Usually used in
 * forms via {@link Ext.ux.colorpick.Button} or {@link Ext.ux.colorpick.Field}.
 *
 * Typically you will need to listen for the change event to be notified when the user
 * chooses a color. Alternatively, you can bind to the "value" config
 *
 *     @example
 *     Ext.create('Ext.ux.colorpick.Selector', {
 *         value     : '993300',  // initial selected color
 *         format   : 'hex6', // by default it's hex6
 *         renderTo  : Ext.getBody(),
 *
 *         listeners: {
 *             change: function (colorselector, color) {
 *                 console.log('New color: ' + color);
 *             }
 *         }
 *     });
 */
Ext.define('Ext.ux.colorpick.Selector', {
    extend: 'Ext.panel.Panel',
    xtype: 'colorselector',
 
    mixins: [
        'Ext.ux.colorpick.Selection'
    ],
 
    controller: 'colorpick-selectorcontroller',
 
    requires: [
        'Ext.field.Text',
        'Ext.field.Number',
        'Ext.ux.colorpick.ColorMap',
        'Ext.ux.colorpick.SelectorModel',
        'Ext.ux.colorpick.SelectorController',
        'Ext.ux.colorpick.ColorPreview',
        'Ext.ux.colorpick.Slider',
        'Ext.ux.colorpick.SliderAlpha',
        'Ext.ux.colorpick.SliderSaturation',
        'Ext.ux.colorpick.SliderValue',
        'Ext.ux.colorpick.SliderHue'
    ],
 
    config: {
        hexReadOnly: false
    },
 
    /**
     * default width and height gives 255x255 color map in Crisp
     */
    width: Ext.platformTags.phone ? 'auto' : 580,
    height: 337,
 
    cls: Ext.baseCSSPrefix + 'colorpicker',
    padding: 10,
 
    layout: {
        type: Ext.platformTags.phone ? 'vbox' : 'hbox',
        align: 'stretch'
    },
 
    defaultBindProperty: 'value',
    twoWayBindable: [
        'value',
        'hidden'
    ],
 
    /**
     * @cfg fieldWidth {Number} Width of the text fields on the container (excluding HEX);
     * since the width of the slider containers is the same as the text field under it
     * (it's the same vbox column), changing this value will also affect the spacing between
     * the sliders.
     */
    fieldWidth: 50,
 
    /**
     * @cfg fieldPad {Number} padding between the sliders and HEX/R/G/B fields.
     */
    fieldPad: 5,
 
    /**
     * @cfg {Boolean} [showPreviousColor]
     * Whether "previous color" region (in upper right, below the selected color preview) should 
     * be shown;
     * these are relied upon by the {@link Ext.ux.colorpick.Button} and the 
     * {@link Ext.ux.colorpick.Field}.
     */
    showPreviousColor: false,
 
    /**
     * @cfg {String} [okButtonText]
     * Text value for "Ok" button;
     * these are relied upon by the {@link Ext.ux.colorpick.Button} and the 
     * {@link Ext.ux.colorpick.Field}.
     */
    okButtonText: 'OK',
 
    /**
     * @cfg {String} [cancelButtonText]
     * Text value for "Cancel" button;
     * these are relied upon by the {@link Ext.ux.colorpick.Button} and the 
     * {@link Ext.ux.colorpick.Field}.
     */
    cancelButtonText: 'Cancel',
 
    /**
     * @cfg {Boolean} [showOkCancelButtons]
     * Whether Ok and Cancel buttons (in upper right, below the selected color preview) should 
     * be shown;
     * these are relied upon by the {@link Ext.ux.colorpick.Button} and the 
     * {@link Ext.ux.colorpick.Field}.
     */
    showOkCancelButtons: false,
 
    /**
     * @event change
     * Fires when a color is selected. Simply dragging sliders around will trigger this.
     * @param {Ext.ux.colorpick.Selector} this 
     * @param {String} color The value of the selected color as per specified {@link #format}.
     * @param {String} previousColor The previous color value.
     */
 
    /**
     * @event ok
     * Fires when OK button is clicked (see {@link #showOkCancelButtons}).
     * @param {Ext.ux.colorpick.Selector} this 
     * @param {String} color The value of the selected color as per specified {@link #format}.
     */
 
    /**
     * @event cancel
     * Fires when Cancel button is clicked (see {@link #showOkCancelButtons}).
     * @param {Ext.ux.colorpick.Selector} this 
     */
 
    listeners: {
        resize: 'onResize',
        show: 'onResize'
    },
 
    initConfig: function(config) {
        var me = this,
            childViewModel = Ext.Factory.viewModel('colorpick-selectormodel');
 
        // Since this component needs to present its value as a thing to which users can
        // bind, we create an internal VM for our purposes.
        me.childViewModel = childViewModel;
 
        if (Ext.platformTags.phone && !(Ext.Viewport.getOrientation() === "landscape")) {
            me.fieldWidth = 35;
        }
 
        if (Ext.platformTags.phone) {
            config.items = [
                me.getPreviewForMobile(childViewModel, config),
                {
                    xtype: 'container',
                    padding: '4px 0 0 0',
                    layout: {
                        type: 'hbox',
                        align: 'stretch'
                    },
                    flex: 1,
                    items: [
                        me.getMapAndHexRGBFields(childViewModel),
                        me.getSliderAndHField(childViewModel),
                        me.getSliderAndSField(childViewModel),
                        me.getSliderAndVField(childViewModel),
                        me.getSliderAndAField(childViewModel)
                    ]
                },
                me.getButtonForMobile(childViewModel, config)
            ];
        }
        else {
            config.items = [
                me.getMapAndHexRGBFields(childViewModel),
                me.getSliderAndHField(childViewModel),
                me.getSliderAndSField(childViewModel),
                me.getSliderAndVField(childViewModel),
                me.getSliderAndAField(childViewModel),
                me.getPreviewAndButtons(childViewModel, config)
            ];
        }
 
        me.childViewModel.bind('{selectedColor}', function(color) {
            me.setColor(color);
        });
 
        this.callParent(arguments);
    },
 
    updateColor: function(color) {
        var me = this;
 
        me.mixins.colorselection.updateColor.call(me, color);
 
        me.childViewModel.set('selectedColor', color);
    },
 
    updatePreviousColor: function(color) {
        this.childViewModel.set('previousColor', color);
    },
 
    // Splits up view declaration for readability
    // "Map" and HEX/R/G/B fields
    getMapAndHexRGBFields: function(childViewModel) {
        var me = this,
            fieldMargin = '' + me.fieldPad + ' 0 0',
            fieldWidth = me.fieldWidth;
 
        return {
            xtype: 'container',
            viewModel: childViewModel,
            cls: Ext.baseCSSPrefix + 'colorpicker-escape-overflow',
            flex: 1,
            autoSize: false,
            layout: {
                type: 'vbox',
                constrainAlign: true
            },
            margin: '0 10 0 0',
            items: [
                // "MAP"
                {
                    xtype: 'colorpickercolormap',
                    reference: 'colorMap',
                    flex: 1,
                    bind: {
                        position: {
                            bindTo: '{selectedColor}',
                            deep: true
                        },
                        hue: '{selectedColor.h}'
                    },
                    listeners: {
                        handledrag: 'onColorMapHandleDrag'
                    }
                },
                // HEX/R/G/B FIELDS
                {
                    xtype: 'container',
                    layout: 'hbox',
                    autoSize: null,
 
                    defaults: {
                        labelAlign: 'top',
                        allowBlank: false
                    },
 
                    items: [{
                        xtype: 'textfield',
                        label: 'HEX',
                        flex: 1,
                        bind: '{hex}',
                        clearable: Ext.platformTags.phone ? false : true,
                        margin: fieldMargin,
                        validators: /^#[0-9a-f]{6}$/i,
                        readOnly: me.getHexReadOnly(),
                        required: true
                    }, {
                        xtype: 'numberfield',
                        clearable: false,
                        label: 'R',
                        bind: '{red}',
                        width: fieldWidth,
                        hideTrigger: true,
                        validators: /^(0|[1-9]\d*)$/i,
                        maxValue: 255,
                        minValue: 0,
                        margin: fieldMargin,
                        required: true
                    }, {
                        xtype: 'numberfield',
                        clearable: false,
                        label: 'G',
                        bind: '{green}',
                        width: fieldWidth,
                        hideTrigger: true,
                        validators: /^(0|[1-9]\d*)$/i,
                        maxValue: 255,
                        minValue: 0,
                        margin: fieldMargin,
                        required: true
                    }, {
                        xtype: 'numberfield',
                        clearable: false,
                        label: 'B',
                        bind: '{blue}',
                        width: fieldWidth,
                        hideTrigger: true,
                        validators: /^(0|[1-9]\d*)$/i,
                        maxValue: 255,
                        minValue: 0,
                        margin: 0,
                        required: true
                    }]
                }
            ]
        };
    },
 
    // Splits up view declaration for readability
    // Slider and H field 
    getSliderAndHField: function(childViewModel) {
        var me = this,
            fieldWidth = me.fieldWidth;
 
        return {
            xtype: 'container',
            viewModel: childViewModel,
            cls: Ext.baseCSSPrefix + 'colorpicker-escape-overflow',
            width: fieldWidth,
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            items: [
                {
                    xtype: 'colorpickersliderhue',
                    reference: 'hueSlider',
                    flex: 1,
                    bind: {
                        hue: '{selectedColor.h}'
                    },
                    width: fieldWidth,
                    listeners: {
                        handledrag: 'onHueSliderHandleDrag'
                    }
                },
                {
                    xtype: 'numberfield',
                    reference: 'hnumberfield',
                    clearable: false,
                    label: 'H',
                    labelAlign: 'top',
                    bind: '{hue}',
                    hideTrigger: true,
                    maxValue: 360,
                    minValue: 0,
                    allowBlank: false,
                    margin: 0,
                    required: true
                }
            ]
        };
    },
 
    // Splits up view declaration for readability
    // Slider and S field 
    getSliderAndSField: function(childViewModel) {
        var me = this,
            fieldWidth = me.fieldWidth,
            fieldPad = me.fieldPad;
 
        return {
            xtype: 'container',
            viewModel: childViewModel,
            cls: [
                Ext.baseCSSPrefix + 'colorpicker-escape-overflow',
                Ext.baseCSSPrefix + 'colorpicker-column-sslider'
            ],
            width: fieldWidth,
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            margin: '' + fieldPad + ' 0 ' + fieldPad,
            items: [
                {
                    xtype: 'colorpickerslidersaturation',
                    reference: 'satSlider',
                    flex: 1,
                    bind: {
                        saturation: '{saturation}',
                        hue: '{selectedColor.h}'
                    },
                    width: fieldWidth,
                    listeners: {
                        handledrag: 'onSaturationSliderHandleDrag'
                    }
                },
                {
                    xtype: 'numberfield',
                    reference: 'snumberfield',
                    clearable: false,
                    label: 'S',
                    labelAlign: 'top',
                    bind: '{saturation}',
                    hideTrigger: true,
                    maxValue: 100,
                    minValue: 0,
                    allowBlank: false,
                    margin: 0,
                    required: true
                }
            ]
        };
    },
 
    // Splits up view declaration for readability
    // Slider and V field 
    getSliderAndVField: function(childViewModel) {
        var me = this,
            fieldWidth = me.fieldWidth;
 
        return {
            xtype: 'container',
            viewModel: childViewModel,
            cls: [
                Ext.baseCSSPrefix + 'colorpicker-escape-overflow',
                Ext.baseCSSPrefix + 'colorpicker-column-vslider'
            ],
            width: fieldWidth,
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            items: [
                {
                    xtype: 'colorpickerslidervalue',
                    reference: 'valueSlider',
                    flex: 1,
                    bind: {
                        value: '{value}',
                        hue: '{selectedColor.h}'
                    },
                    width: fieldWidth,
                    listeners: {
                        handledrag: 'onValueSliderHandleDrag'
                    }
                },
                {
                    xtype: 'numberfield',
                    reference: 'vnumberfield',
                    clearable: false,
                    label: 'V',
                    labelAlign: 'top',
                    bind: '{value}',
                    hideTrigger: true,
                    maxValue: 100,
                    minValue: 0,
                    allowBlank: false,
                    margin: 0,
                    required: true
                }
            ]
        };
    },
 
    // Splits up view declaration for readability
    // Slider and A field 
    getSliderAndAField: function(childViewModel) {
        var me = this,
            fieldWidth = me.fieldWidth;
 
        return {
            xtype: 'container',
            viewModel: childViewModel,
            cls: Ext.baseCSSPrefix + 'colorpicker-escape-overflow',
            width: fieldWidth,
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            margin: '0 0 0 ' + me.fieldPad,
            items: [
                {
                    xtype: 'colorpickerslideralpha',
                    reference: 'alphaSlider',
                    flex: 1,
                    bind: {
                        alpha: '{alpha}',
                        color: {
                            bindTo: '{selectedColor}',
                            deep: true
                        }
                    },
                    width: fieldWidth,
                    listeners: {
                        handledrag: 'onAlphaSliderHandleDrag'
                    }
                },
                {
                    xtype: 'numberfield',
                    reference: 'anumberfield',
                    clearable: false,
                    label: 'A',
                    labelAlign: 'top',
                    bind: '{alpha}',
                    hideTrigger: true,
                    maxValue: 100,
                    minValue: 0,
                    allowBlank: false,
                    margin: 0,
                    required: true
                }
            ]
        };
    },
 
    // Splits up view declaration for readability
    // Preview current/previous color squares and OK and Cancel buttons
    getPreviewAndButtons: function(childViewModel, config) {
        // selected color preview is always shown
        var items = [{
            xtype: 'colorpickercolorpreview',
            flex: 1,
            bind: {
                color: {
                    bindTo: '{selectedColor}',
                    deep: true
                }
            }
        }];
 
        // previous color preview is optional
        if (config.showPreviousColor) {
            items.push({
                xtype: 'colorpickercolorpreview',
                flex: 1,
                bind: {
                    color: {
                        bindTo: '{previousColor}',
                        deep: true
                    }
                },
                listeners: {
                    click: 'onPreviousColorSelected'
                }
            });
        }
 
        // Ok/Cancel buttons are optional
        if (config.showOkCancelButtons) {
            items.push(
                {
                    xtype: 'button',
                    text: this.okButtonText,
                    margin: '10 0 0 0',
                    handler: 'onOK'
                },
                {
                    xtype: 'button',
                    text: this.cancelButtonText,
                    margin: '10 0 0 0',
                    handler: 'onCancel'
                }
            );
        }
 
        return {
            xtype: 'container',
            viewModel: childViewModel,
            cls: Ext.baseCSSPrefix + 'colorpicker-column-preview',
            width: 70,
            margin: '0 0 0 10',
            items: items,
            layout: {
                type: 'vbox',
                align: 'stretch'
            }
        };
    },
    getPreviewForMobile: function(childViewModel, config) {
        // selected color preview is always shown
        var items = [{
            xtype: 'colorpickercolorpreview',
            flex: 1,
            bind: {
                color: {
                    bindTo: '{selectedColor}',
                    deep: true
                }
            }
        }];
 
        // previous color preview is optional
        if (config.showPreviousColor) {
            items.push({
                xtype: 'colorpickercolorpreview',
                flex: 1,
                bind: {
                    color: {
                        bindTo: '{previousColor}',
                        deep: true
                    }
                },
                listeners: {
                    click: 'onPreviousColorSelected'
                }
            });
        }
 
        return {
            xtype: 'container',
            viewModel: childViewModel,
            cls: Ext.baseCSSPrefix + 'colorpicker-column-mobile-preview',
            // width: '100%',
            height: 40,
            margin: '10 0 10 0',
            items: items,
            layout: {
                type: 'hbox',
                align: 'stretch'
            }
        };
    },
    getButtonForMobile: function(childViewModel, config) {
        // selected color preview is always shown
        var items = [];
 
        // Ok/Cancel buttons are optional
        if (config.showOkCancelButtons) {
            items.push(
                {
                    xtype: 'container',
                    flex: 1
                },
                {
                    xtype: 'button',
                    text: this.cancelButtonText,
                    minWidth: 70,
                    margin: '5 5 0 5',
                    handler: 'onCancel'
                },
                {
                    xtype: 'button',
                    text: this.okButtonText,
                    margin: '5 5 0 5',
                    minWidth: 50,
                    handler: 'onOK'
                }
            );
 
            return {
                xtype: 'container',
                viewModel: childViewModel,
                cls: Ext.baseCSSPrefix + 'colorpicker-column-mobile-button',
                width: '100%',
                height: 40,
                margin: '0',
                align: 'right',
                items: items,
                layout: {
                    type: 'hbox',
                    align: 'stretch'
                }
            };
        }
 
        return {};
    }
});