if(typeof window.econda == 'undefined') {
    window.econda = {};
}
var econda = window.econda;

if(typeof econda.base == 'undefined') {
    econda.base = {};
}
/**
 * Base Object providing some common support for configs, standard set/get method.
 * Do not use this object directly, it's a base class for other objects.
 * 
 * @private
 * @class {econda.base.Object}
 * @param cfg
 * @returns {econda.base.Object}
 */
econda.base.Object = function(defaultPropertyName)
{
    /**
     * We assign private properties for extending objects here
     * See this.setup().
     * @private
     * @property {Object} __p
     */
    var __p;
    
    /**
     * Converts property names to setter function names
     * myProperty => setMyProperty
     * 
     * @method
     * @private
     * @param {String} propertyName Name of class property
     * @return {String} Name of setter function for given property
     */
    this.getSetterName = function (propertyName) 
    {
        return "set" + propertyName.substr(0,1).toUpperCase() + propertyName.substr(1);
    };
    
    /**
     * Set multiple properties.
     * 
     * Example:
     *     // set multiple properties
     *     obj.set({
     *         propertyName: newValue,
     *         property2: newValue2
     *     });
     *     
     *     // set single property
     *     // you should use obj.setPropertyName(newValue) instead
     *     obj.set("propertyName", newValue);
     *     
     *     // set default property
     *     obj.set(newValue);
     *  
     * @method
     * @param {Object/String} cnf Object containing multiple properties and values or name of property
     * @param {Mixed} newValue (Optional)
     */
    this.set = function(cfg) 
    {
        var cmp = this;
        
        // handles set({propertyName: newValue})
        if (typeof cfg == 'object') {
            for ( var propertyName in cfg) {
                var functionName = cmp.getSetterName(propertyName);
                if (typeof this[functionName] != 'undefined') {
                    this[functionName](cfg[propertyName]);
                } else {
                    econda.debug.error("Cannot set " + propertyName + ": no setter defined.");
                }
            }
        
        // handles set("propertyName", newValue)
        } else if(typeof cfg == 'string' && arguments.length == 2) {
            var propertyName = cfg;
            var newValue = arguments[1];
            var functionName = cmp.getSetterName(propertyName);
            if (typeof this[functionName] != 'undefined') {
                this[functionName](newValue);
            } else {
                econda.debug.error("Cannot set " + propertyName + ": no setter defined.");
            }
            
        // handles set(newValue)
        } else if(typeof cfg != 'undefined' && cmp.__defaultProperty) {
            var functionName = cmp.getSetterName(cmp.__defaultProperty);
            cmp[functionName](cfg);
        }
        return this;
    };
    
    /**
     * Handles config options that we got in a constructor.
     * Config options might be an instance of the given object, a config object or
     * the value of standard property.
     * 
     * @method
     * @private
     * @param {Number/String/Object} cfg Constructor value
     */
    this.processConfig = function(cfg)
    {
        // FIXME
        if(cfg instanceof econda.base.Object) {
            return cfg;
        } else {
            this.set(cfg);
            return this;
        }
    };
    
    /**
     * Private setup function. Handles setup of config and some additional things
     * @method
     * @private
     */
    this.setup = function(cfg, privateProperties)
    {
        var ret = this;
        __p = privateProperties;
        
        // process configuration
        if(typeof cfg != 'undefined') {
            ret = this.processConfig(cfg);
        }
        
        // provide debug information
        if(econda.debug.enabled) {
            this.__privateData = privateProperties;
        }
        return ret;
    };
    
    /**
     * Add custom fieldset // NOT SUPPORTED
     * @ignore
     * @method
     * @chainable
     * @param {econda.CustomFieldset/Object} fieldSet
     */
    this.addCustomFields = function(fieldSet)
    {
        if(typeof __p["customFieldsets"] == 'undefined') {
            econda.debug.error("Object doesn't support custom fieldsets.", this);
            return this;
        }
        if(fieldSet instanceof Array) {
            for(var n=0; n<fieldSet.length; n++) {
                this.addCustomFields(fieldSet[n]);
            }
        } else {
            __p["customFieldsets"].push(new econda.CustomFieldset(fieldSet));
        }
        return this;
    };
    
    /**
     * Set custom fieldsets (replaces existing data)
     * @ignore
     * @method
     * @chainable
     * @param {econda.CustomFieldset/Object/Array} fieldSet
     */
    this.setCustomFields = function(fieldSet)
    {
        this.clearCustomFields();
        return this;
    };

    /**
     * Removes all custom fieldsets
     * @ignore
     * @method
     */
    this.clearCustomFields = function()
    {
        __p["customFieldsets"].length = 0;
        return this;
    };
}