/**
* combo - jQuery EasyUI 
* 
* Licensed under the GPL:
*   http://www.gnu.org/licenses/gpl.txt
*
* Copyright 2010 stworthy [ stworthy@gmail.com ] 
* 
* Dependencies:
*   layoutpanel
*   validatebox
*   
* Alter:
*  Date:2011-07-09
*  Author:CIHO
*/
(function ($) {
    function setSize(target, width) {
        var opts = $.data(target, 'combo').options;
        var combo_ciho = $.data(target, 'combo').combo_ciho;
        var layoutpanel = $.data(target, 'combo').layoutpanel;

        if (width) opts.width = width;

        if (isNaN(opts.width)) {
            opts.width = combo_ciho.find('input.combo-text').outerWidth();
        }
        var arrowWidth = combo_ciho.find('.combo-arrow').outerWidth();
        var width = opts.width - arrowWidth;
        combo_ciho.find('input.combo-text').width(width);

        layoutpanel.layoutpanel('resize', {
            width: (opts.panelWidth ? opts.panelWidth : combo_ciho.outerWidth()),
            height: opts.panelHeight
        });
    }

    /**
    * create the combo_ciho component.
    */
    function init(target) {
        $(target).hide();

        var span = $('<span class="combo"></span>').insertAfter(target);
        var input = $('<input type="text" class="combo-text">').appendTo(span);
        $('<span><span class="combo-arrow"></span></span>').appendTo(span);
        $('<input type="hidden" class="combo-value">').appendTo(span);
        var layoutpanel = $('<div class="combo-layoutpanel"></div>').appendTo('body');
        layoutpanel.layoutpanel({
            doSize: false,
            closed: true,
            style: {
                position: 'absolute'
            },
            onOpen: function () {
                $(this).layoutpanel('resize');
            }
        });

        var name = $(target).attr('name');
        if (name) {
            span.find('input.combo-value').attr('name', name);
            $(target).removeAttr('name').attr('comboName', name);
        }
        input.attr('autocomplete', 'off');

        return {
            combo_ciho: span,
            layoutpanel: layoutpanel
        };
    }

    function destroy(target) {
        $.data(target, 'combo').layoutpanel.layoutpanel('destroy');
        $.data(target, 'combo').combo_ciho.remove();
        $(target).remove();
    }

    function bindEvents(target) {
        var opts = $.data(target, 'combo').options;
        var combo_ciho = $.data(target, 'combo').combo_ciho;
        var layoutpanel = $.data(target, 'combo').layoutpanel;
        var input = combo_ciho.find('.combo-text');
        var arrow = combo_ciho.find('.combo-arrow');

        $(document).unbind('.combo');
        combo_ciho.unbind('.combo');
        layoutpanel.unbind('.combo');
        input.unbind('.combo');
        arrow.unbind('.combo');

        //无论combobox是否可用，都为其绑定【鼠标按下】关闭panel的事件。
        $(document).bind('mousedown.combo', function (e) {
            $('div.combo-layoutpanel').layoutpanel('close');
        });
        layoutpanel.bind('mousedown.combo', function (e) {
            return false;
        });
        if (!opts.disabled) {
            input.bind('focus.combo', function () {
                showPanel(target);
                opts.onfocus.call(target); //ciho
            }).bind('blur.combo', function () {//ciho
                opts.onblur.call(target);   //ciho
            }).bind('mousedown.combo', function (e) {
                e.stopPropagation();
                $(document).trigger("mousedown.hasDatepicker");
            }).bind('keydown.combo', function (e) {
                if (e.keyCode == 9) {//Tab
                    hidePanel(target);
                }
            }).bind('keyup.combo', function (e) {
                switch (e.keyCode) {
                    case 37: // left
                    case 38: // up
                        opts.selectPrev.call(target);
                        break;
                    case 39: // right
                    case 40: // down
                        opts.selectNext.call(target);
                        break;
                    case 13: // enter
                        opts.selectCurr.call(target);
                        opts.enterDown.call(target); //ciho
                        break;
                    case 27: // esc
                        hidePanel(target);
                        break;
                    case 9: //Tab
                        //hidePanel(target);
                        break;
                    default:
                        if (opts.editable) {
                            opts.filter.call(target, $(this).val());
                        }
                }
                return false;
            });

            arrow.bind('click.combo', function () {
                input.focus();
            }).bind('mouseenter.combo', function () {
                $(this).addClass('combo-arrow-hover');
            }).bind('mouseleave.combo', function () {
                $(this).removeClass('combo-arrow-hover');
            });
        }
    }

    /**
    * show the drop down layoutpanel.
    */
    function showPanel(target) {
        //关闭所有combobox,月份，日期控件的panel
        //$(".layoutpanel").css("display", "none");
        $(".ciho-Tree").css("display", "none");
        //$(".ui-datepicker").css("display", "none");
        $(document).trigger("mousedown");

        //取不到值，加载下拉列表所有的值
        var strCurVal = getValue(target);
        if (!strCurVal) {
            cihoLoadAllDatas(target, "");     //ciho
        }

        var combo_ciho = $.data(target, 'combo').combo_ciho;
        var layoutpanel = $.data(target, 'combo').layoutpanel;

        //自定义修改
        layoutpanel.layoutpanel('layoutpanel').css('z-index', "50000009");
        //        if ($.fn.window) {
        //            layoutpanel.layoutpanel('layoutpanel').css('z-index', $.fn.window.defaults.zIndex++);
        //        }

        layoutpanel.layoutpanel('open');

        (function () {
            if (layoutpanel.is(':visible')) {
                var top = combo_ciho.offset().top + combo_ciho.outerHeight();
                if (top + layoutpanel.outerHeight() > $(window).height() + $(document).scrollTop()) {
                    top = combo_ciho.offset().top - layoutpanel.outerHeight();
                }
                if (top < $(document).scrollTop()) {
                    top = combo_ciho.offset().top + combo_ciho.outerHeight();
                }
                layoutpanel.layoutpanel('move', {
                    left: combo_ciho.offset().left,
                    top: top
                });
                setTimeout(arguments.callee, 200);
            }
        })();
    }

    /**
    * hide the drop down layoutpanel.
    */
    function hidePanel(target) {
        var layoutpanel = $.data(target, 'combo').layoutpanel;
        layoutpanel.layoutpanel('close');
    }

    function validate(target, doit) {
        if ($.fn.validatebox) {
            var opts = $.data(target, 'combo').options;
            var input = $.data(target, 'combo').combo_ciho.find('input.combo-text');
            input.validatebox(opts);
            if (doit) {
                input.validatebox('validate');
                input.trigger('mouseleave');
            }
        }
    }

    function setDisabled(target, disabled) {
        var opts = $.data(target, 'combo').options;
        var combo_ciho = $.data(target, 'combo').combo_ciho;
        if (disabled) {
            opts.disabled = true;
            $(target).attr('disabled', true);
            combo_ciho.find('.combo-value').attr('disabled', true);
            combo_ciho.find('.combo-text').attr('disabled', true);
        } else {
            opts.disabled = false;
            $(target).removeAttr('disabled');
            combo_ciho.find('.combo-value').removeAttr('disabled');
            combo_ciho.find('.combo-text').removeAttr('disabled');
        }
    }

    function clear(target) {
        var combo_ciho = $.data(target, 'combo').combo_ciho;
        combo_ciho.find('input.combo-value:gt(0)').remove();
        combo_ciho.find('input.combo-value').val('');
        combo_ciho.find('input.combo-text').val('');
    }

    function getText(target) {
        var combo_ciho = $.data(target, 'combo').combo_ciho;
        return combo_ciho.find('input.combo-text').val();
    }

    function setText(target, text) {
        var combo_ciho = $.data(target, 'combo').combo_ciho;
        combo_ciho.find('input.combo-text').val(text);
        validate(target, true);
    }

    function getValues(target) {
        var values = [];
        var combo_ciho = $.data(target, 'combo').combo_ciho;
        combo_ciho.find('input.combo-value').each(function () {
            values.push($(this).val());
        });
        return values;
    }

    function setValues(target, values) {
        var opts = $.data(target, 'combo').options;
        var oldValues = getValues(target);

        var combo_ciho = $.data(target, 'combo').combo_ciho;
        combo_ciho.find('input.combo-value').remove();
        var name = $(target).attr('comboName');
        for (var i = 0; i < values.length; i++) {
            var input = $('<input type="hidden" class="combo-value">').appendTo(combo_ciho);
            if (name) input.attr('name', name);
            input.val(values[i]);
        }

        var tmp = [];
        for (var i = 0; i < oldValues.length; i++) {
            tmp[i] = oldValues[i];
        }
        var aa = [];
        for (var i = 0; i < values.length; i++) {
            for (var j = 0; j < tmp.length; j++) {
                if (values[i] == tmp[j]) {
                    aa.push(values[i]);
                    tmp.splice(j, 1);
                    break;
                }
            }
        }

        if (aa.length != values.length || values.length != oldValues.length) {
            if (opts.multiple) {
                opts.onChange.call(target, values, oldValues);
            } else {
                opts.onChange.call(target, values[0], oldValues[0]);
            }
        }
    }

    function getValue(target) {
        var values = getValues(target);
        return values[0];
    }

    function setValue(target, value) {
        setValues(target, [value]);
    }

    /**
    * parse options from markup.
    */
    function parseOptions(target) {
        var t = $(target);
        return {
            width: (parseInt(target.style.width) || undefined),
            panelWidth: (parseInt(t.attr('panelWidth')) || undefined),
            panelHeight: (t.attr('panelHeight') == 'auto' ? 'auto' : parseInt(t.attr('panelHeight')) || undefined),
            separator: (t.attr('separator') || undefined),
            multiple: (t.attr('multiple') ? (t.attr('multiple') == 'true' || t.attr('multiple') == true) : undefined),
            editable: (t.attr('editable') ? t.attr('editable') == 'true' : undefined),
            disabled: (t.attr('disabled') ? true : undefined),
            required: (t.attr('required') ? (t.attr('required') == 'true' || t.attr('required') == true) : undefined),
            missingMessage: (t.attr('missingMessage') || undefined)
        };
    }

    /**
    * set focus
    */
    function focus(target) {
        var combo_ciho = $.data(target, 'combo').combo_ciho;
        combo_ciho.find('input.combo-text').focus();
    }

    $.fn.combo_ciho = function (options, param) {
        if (typeof options == 'string') {
            return $.fn.combo_ciho.methods[options](this, param);
        }

        options = options || {};
        return this.each(function () {
            var state = $.data(this, 'combo');
            if (state) {
                $.extend(state.options, options);
            } else {
                var r = init(this);
                state = $.data(this, 'combo', {
                    options: $.extend({}, $.fn.combo_ciho.defaults, parseOptions(this), options),
                    combo_ciho: r.combo_ciho,
                    layoutpanel: r.layoutpanel
                });
                $(this).removeAttr('disabled');
            }
            $('input.combo-text', state.combo_ciho).attr('readonly', !state.options.editable);
            setDisabled(this, state.options.disabled);
            setSize(this);
            bindEvents(this);
            validate(this);
        });
    };

    $.fn.combo_ciho.methods = {
        parseOptions: function (jq) {
            return parseOptions(jq[0]);
        },
        options: function (jq) {
            return $.data(jq[0], 'combo').options;
        },
        layoutpanel: function (jq) {
            return $.data(jq[0], 'combo').layoutpanel;
        },
        textbox: function (jq) {
            return $.data(jq[0], 'combo').combo_ciho.find('input.combo-text');
        },
        destroy: function (jq) {
            return jq.each(function () {
                destroy(this);
            });
        },
        resize: function (jq, width) {
            return jq.each(function () {
                setSize(this, width);
            });
        },
        showPanel: function (jq) {
            return jq.each(function () {
                showPanel(this);
            });
        },
        hidePanel: function (jq) {
            return jq.each(function () {
                hidePanel(this);
            });
        },
        disable: function (jq) {
            return jq.each(function () {
                setDisabled(this, true);
                bindEvents(this);
            });
        },
        enable: function (jq) {
            return jq.each(function () {
                setDisabled(this, false);
                bindEvents(this);
            });
        },
        clear: function (jq) {
            return jq.each(function () {
                clear(this);
            });
        },
        getText: function (jq) {
            return getText(jq[0]);
        },
        setText: function (jq, text) {
            return jq.each(function () {
                setText(this, text);
            });
        },
        getValues: function (jq) {
            return getValues(jq[0]);
        },
        setValues: function (jq, values) {
            return jq.each(function () {
                setValues(this, values);
            });
        },
        getValue: function (jq) {
            return getValue(jq[0]);
        },
        setValue: function (jq, value) {
            return jq.each(function () {
                setValue(this, value);
            });
        },
        focus: function (jq) {
            return jq.each(function () {
                focus(this);
            });
        }
    };
    //加载所有下拉项
    function cihoLoadAllDatas(target, query) {
        var data = $.data(target, 'combobox').data;
        var layoutpanel = $(target).combo_ciho('layoutpanel');
        layoutpanel.find('div.combobox-item').each(function () {
            var item = $(this);
            item.show();
        });
    }

    $.fn.combo_ciho.defaults = {
        width: 'auto',
        panelWidth: null,
        panelHeight: 200,
        multiple: false,
        separator: ',',
        editable: true,
        disabled: false,
        required: false,
        missingMessage: 'This field is required.',

        selectPrev: function () { },
        selectNext: function () { },
        selectCurr: function () { },
        enterDown: function () { }, //ciho
        onfocus: function () { }, //ciho
        onblur: function () { }, //ciho
        filter: function (query) { },

        onChange: function (newValue, oldValue) { }
    };
})(jQuery);
