define('jls/gui/Style', ['jls/lang/Class'], function (Class) {

var Style;
Style = Class.create( /** @lends jls.gui.Style.prototype */
{
    /**
     * Creates a style.
     * 
     * @param {Object} [properties] The style properties to activate.
     * @constructs
	 * @class This class provides style for Element.
     */
    initialize : function(properties) {
    	this._properties = properties || {}; // TODO Copy properties?
    	this._activated = false;
    	this._parent = null;
    	this._handler = Class.emptyFunction;
        this._inheritedProperties = Style.defaultInherited;
        this._defaultProperties = Style.defaultAcquired;
    },
    /**
     * Activates this style.
     * 
     * @param {Object} [properties] The style properties to activate.
     */
    activate : function() {
    	if (this._activated) {
    		return;
    	}
        //jls.logger.trace('activate()');
    	this._activated = true;
        this.setProperties(this._properties);
    	this._properties = null;
    },
    /**
     * Sets a handler on this style.
     * 
     * @param {Function} handler The element to link to this style.
     * @returns {Function} The previous handler if any.
     */
    setHandler : function(handler) {
    	var previous = this._handler;
    	this._handler = handler;
        return previous;
    },
    setParent : function(parent) {
        this._parent = parent;
    },
    setInheritedProperties : function(properties) {
        this._inheritedProperties = properties;
    },
    setDefaultProperties : function(properties) {
        this._defaultProperties = properties;
    },
    /**
     * Returns the value of a property.
     * 
     * @param {String} key The property key.
     * @returns {Object} The property value or null.
     */
    getPropertyValue : function(key) {
        /*var getter = key.camelize('get');
        if (Object.isFunction(this[getter])) {
            return this[getter]();
        }*/
        key = key.camelize();
        //jls.logger.trace('getPropertyValue(' + key + ')');
        if (! this._activated) {
            if (key in this._properties) {
            	this[key] = this._properties[key]; // Will not be activated
                return this._properties[key];
            }
        }
        if (key in this) {
            return this[key];
        }
        if (key in this._inheritedProperties) {
            //jls.logger.trace('try to inherite');
            if (this._parent != null) {
                var value = this._parent.getPropertyValue(key);
                if (value != null) {
                    return value;
                }
            }
            return this._inheritedProperties[key];
        }
        if (key in this._defaultProperties) {
            return this._defaultProperties[key];
        }
        return null;
    },
    /**
     * Removes a property.
     * 
     * @param {String} key The property key.
     * @returns {Object} The previous property value if any.
     */
    removeProperty : function(key) {
        key = key.camelize();
        if (! (key in this)) {
            return null;
        }
        var previous = this[key];
        delete this[key];
        this._handler(key, previous, null);
        return previous;
    },
    /**
     * Sets a property.
     * 
     * @param {String} key The property key.
     * @param {String} value The value of the property.
     * @returns {Object} The previous property value if any.
     */
    setProperty : function(key, value) {
        if ((typeof value == 'undefined') || (value == null)) {
            return this.removeProperty(key);
        }
        key = key.camelize();
        var previous = key in this ? this[key] : null;
        //jls.logger.trace('setProperty(' + key + ', "' + value + '") previous: "' + previous + '"');
        if (value == previous) {
        	return previous;
        }
        this[key] = value;
        this._handler(key, previous, value);
        return previous;
    },
    /**
     * Sets properties.
     * 
     * @param {Object} properties The style properties to set.
     * @param {Array} [list] The property to set.
     */
    setProperties : function(properties, list) {
    	if (Object.isArray(list)) {
            for (var i = 0; i < list.length; i++) {
            	var k = list[i];
                if (k in properties) {
                    this.setProperty(k, properties[k]);
                }
            }
    	} else {
            for (var k in properties) {
                this.setProperty(k, properties[k]);
            }
    	}
        return this;
    }
});

Object.extend(Style,
{
    defaultInherited: {
        fontFamily: 'Arial',
        fontSize: 12,
        marginTop: 0,
        marginBottom: 0,
        marginLeft: 0,
        marginRight: 0,
        overflow: 'visible', // visible | hidden | scroll | auto
        direction: 'ltr', // ltr | rtl
        verticalPosition: 'top', // top | middle | bottom
        textAlign: 'left', // left | right | center | justify | leading | trailing
        verticalAlign: 'bottom' // top | middle | bottom
    },
    defaultAcquired: { // noninheritable
    	clear: 'none', // none | left | right | both
    	display: 'inline', // inline | block | none
        position: 'relative', // static | relative | absolute | fixed
        visibility: 'visible', // visible | hidden | collapse
        left: null,
        top: null,
        width: null,
        height: null
    }
});


return Style;
});
