FR.widget = {
    opts: {
        zIndex: 8000,
        num: 0
    }
};

/**
 * 这是一个抽象类,是所有控件的父类,不能直接使用,只能使用其具体的子类
 * @class FR.Widget
 * @extends FR.OB
 * @abstract
 *
 * @cfg {JSON} options 配置属性
 * @cfg {String} [options.widgetName=""] 控件名
 * @cfg {Object} options.value 控件值
 * @cfg {Number} options.width 控件宽度
 * @cfg {Number} options.height 控件高度
 * @cfg {Boolean} [options.disabled=false] 控件的可用性
 * @cfg {Boolean} [options.invisible=false] 控件的可见性
 *
 */
FR.Widget = FR.extend(FR.OB, {

    /**
     * 默认的配置
     * @private
     */
    _defaultConfig: function () {
        return $.extend(FR.Widget.superclass._defaultConfig.apply(this, arguments), {
            widgetName: "",
            disabled: false,
            invisible: false,
            usedAsEditor: false,
            resultWidgets : {}
        });
    },

    /**
     * 初始化方法
     * @private
     */
    _init: function () {
        FR.Widget.superclass._init.apply(this, arguments);
        this._initRoot();
        this._initElementSize();
        this._initVisualEffects();
        this._initNameEffects();
    },

    /**
     * 初始化根节点
     * @private
     */
    _initRoot : function(){
        /*alex:如果options里面有renderEl这个属性,就使用这个属性对应的jquery对象*/
        if (this.options.renderEl != null) {
            /**
             * @property {jQuery} element 控件的根节点元素
             */
            this.element = $(this.options.renderEl);
        } else {
            this.element = this._defaultRoot();
        }
        if (this.options.baseCls) {
            this.element.addClass(this.options.baseCls);
        }
    },

    /**
     * 初始计算高度宽度相关的尺寸
     * @private
     */
    _initElementSize : function() {
        var o = this.options;
        if (FR.isWidthOrHeight(o.width)) {
            this.element.css({
                width: o.width - FR.fixBoxModelWidth(this.element)
            });
        } else {
            if (o.width == 'auto') {
                this.element.width('auto');
            }else if(this.isStringTypeNumber(o.width)){
                this.element.width(parseInt(o.width));
            }
        }
        if (FR.isWidthOrHeight(o.height)) {
            this.element.css({
                height: o.height - FR.fixBoxModelHeight(this.element)
            });
        } else {
            if (o.height == 'auto') {
                this.element.height('auto');
            }else if(this.isStringTypeNumber(o.height)){
                this.element.height(parseInt(o.height));
            }
        }
        var self = this;
        this.element.bind(FR.Events.RESIZE, function (event, give) {
            self.doResize(give);
        });
    },

    /**
     * "24"这种形式的
     * @param o 宽度或者高度
     * @returns {boolean} 是否是"24"这种形式
     */
    isStringTypeNumber: function(o){
        return !isNaN(parseInt(o));
    },

    /**
     * 初始化视觉相关效果
     * @private
     */
    _initVisualEffects : function() {
        this[this.options.disabled ? 'disable' : 'enable']();
        if(this.options.invisible) {
            this.setVisible(false);
        }
    },

    /**
     * 初始化和名字相关的计算
     * @private
     */
    _initNameEffects : function() {
        var o = this.options;
        if (o.widgetName) {
            this.element.attr({
                widgetName: o.widgetName
            });
        }
        FR.widget.opts.num++;
        if (o.widgetName) {
            this._addWidget(o.widgetName, this);
        } else {
            this._addWidget("_widget_" + FR.widget.opts.num, this);
        }
    },

    /**
     * 添加此控件中所包含的空间,以名字/值做对应
     * @param {String} name 要添加的控件的名字
     * @param {FR.Widget} widget  要添加的控件
     * @private
     */
    _addWidget : function(name, widget) {
        this.options.resultWidgets[name] = widget;
    },

    /**
     * 获取控件名字
     * @return 控件名
     */
    getName : function() {
        return this.options.widgetName;
    },

    /**
     * 获取该控件中所添加的子控件
     * @param {String} name 要获取的子控件的名字
     * @returns {FR.Widget} 具有指定名字的控件
     */
    getWidgetByName : function(name) {
        return this.options.resultWidgets[name];
    },

    /**
     * 获取控件的显示值,所有表单控件都应该实现这个方法
     * @returns {String} 获取控件的显示的值
     */
    getText : function() {

    },

    /**
     * 设置控件的显示值
     * @param {String} text 要设置的显示值
     */
    setText : function(text) {

    },
    /**
     * 获取控件的实际值
     * @returns {Object} 获取控件的实际值
     */
    getValue: function () {

    },

    /**
     * 设置控件的值
     * @param {Object} value 要设置的实际值
     * @param {Boolean} shouldFireEvent 是否触发事件
     */
    setValue: function (value, shouldFireEvent) {

    },
    /**
     * 获取控件类型,
     */
    getType: function () {
        return this.options.type;
    },

    /**
     * 判断控件是否可用
     * @returns {Boolean} 返回true表示可用,返回false表示不可用
     */
    isEnabled: function () {
        return !this.options.disabled;
    },

    /**
     * 设置控件的可用性
     * @param {Boolean} enable 如果参数值为true则设置控件为可用,如果参数值为false则设置控件为不可用
     */
    setEnable: function (enable) {
        if (enable === true) {
            this.options.disabled = false;
            this.element.addClass('ui-state-enabled');
            this.element.removeClass('ui-state-disabled');
        } else if (enable === false) {
            this.options.disabled = true;
            this.element.addClass('ui-state-disabled');
            this.element.removeClass('ui-state-enabled');
        }

    },

    /**
     * 判断控件是否可见
     * @returns {Boolean} 可见则返回true,不可见则返回false
     */
    isVisible: function () {
        return !this.options.invisible;
    },

    /**
     * 设置控件的可见性
     * @param {Boolean} visible  如果参数值为true则设置控件为可见,如果参数值为false则设置控件为不可见
     */
    setVisible: function (visible) {
        /*只有参数为true/false的时候才有反应,其他参数一律不作任何改变*/
        if (visible === true) {
            this.options.invisible = false;
            this.element.show();
        } else if (visible === false) {
            this.options.invisible = true;
            this.element.hide();
        }
    },

    /**
     * 设置控件的初始值,一般情况和setValue一样,在初始值为数据绑定的时候需要动态加载数据
     * @param source 初始值
     */
    setSource: function (source) {
        this.setValue(source);
    },

    /**
     * 控件能否在填报中用做编辑器
     * @returns {Boolean} 可以用做编辑器则返回true,比如FR.ComboBoxEditor;否则返回false
     */
    couldUsedAsEditor: function () {
        return this.options.usedAsEditor;
    },

    /**
     * 恢复控件到初始状态,一般用于重新取值
     */
    reset: function () {

    },

    /**
     * 重新设置控件的大小和位置
     * @param {Object} [give] 给定的尺寸和位置
     * @param {Number} give.width 给定的宽度
     * @param {Number} give.height 给定的高度
     * @param {Number} give.top 距离其父容器顶部的距离
     * @param {Number} give.left 距离其父容器左侧的距离
     */
    doResize: function (give) {
        var opts = this.options;
        var cc = this.element;
        if (give) {
            if (give.width) {
                opts.width = give.width;
            }
            if (give.height) {
                opts.height = give.height;
            }
            if (give.left != null) {
                opts.left = give.left;
            }
            if (give.top != null) {
                opts.top = give.top;
            }
        } else if (opts.fit === true) {
            var p = cc.parent();
            var p_width = p.width();
            var p_height = p.height();
            opts.width = p_width;
            opts.height = p_height;
        }
        this.element.width(opts.width);
        this.element.height(opts.height);
    },

    /**
     * 销毁整个控件的dom结构
     */
    destroy: function () {
        this.element.each(function () {
            $(this).remove();
            if (FR.Browser.isIE()) {
                this.outerHTML = '';
            }
        });
    },

    /**
     * @returns {jQuery} 返回控件DOM的根节点标签
     * @private
     */
    _defaultRoot: function () {
        return $("<div/>");
    },

    /**
     * @deprecated
     * {@link #setEnable}
     */
    disable: function () {
        this.setEnable(false);
    },
    /**
     * @deprecated
     * {@link #setEnable}
     */
    enable: function () {
        this.setEnable(true);
    },
    /**
     * @deprecated
     * {@link #setVisible}
     */
    invisible: function () {
        this.setVisible(false);
    },
    /**
     * @deprecated
     * {@link #setVisible}
     */
    visible: function () {
        this.setVisible(true);
    }
});