/// <reference path="../debug.ts" />
/// <reference path="../util/ArrayUtils.ts" />
var econda;
(function (econda) {
    var base;
    (function (base) {
        /**
         * Base class for sdk classes. Provides some common helpers.
         * @class econda.base.BaseClass
         */
        var BaseClass = (function () {
            function BaseClass() {
                /**
                 * Name of property to use if constructor is called with parameters != Object
                 * @private
                 */
                this.__defaultProperty = null;
            }
            /**
             * Initialized object based on configuration.
             * @private (for docs)
             * @param {Object} cfg
             */
            BaseClass.prototype.initConfig = function (cfg, defaultPropertyName) {
                if (defaultPropertyName === void 0) { defaultPropertyName = null; }
                if (defaultPropertyName != null) {
                    this.__defaultProperty = defaultPropertyName;
                }
                if (typeof cfg != 'undefined') {
                    this.set(cfg);
                }
            };
            /**
             * 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)
             */
            BaseClass.prototype.set = function (cfg, newValue) {
                var cmp = this;
                var propertyName, functionName;
                // handles set({propertyName: newValue})
                if (typeof cfg == 'object') {
                    for (propertyName in cfg) {
                        functionName = cmp.getSetterName(propertyName);
                        if (typeof this[functionName] != 'undefined') {
                            this[functionName](cfg[propertyName]);
                        }
                        else {
                            econda.debug.error('Cannot set ' + propertyName + ' in ' + this._getClassName() + ': no setter defined.');
                        }
                    }
                }
                else if (typeof cfg == 'string' && arguments.length == 2) {
                    propertyName = cfg;
                    functionName = cmp.getSetterName(propertyName);
                    if (typeof this[functionName] != 'undefined') {
                        this[functionName](newValue);
                    }
                    else {
                        econda.debug.error('Cannot set ' + propertyName + ' in ' + this._getClassName() + ': no setter defined.');
                    }
                }
                else if (typeof cfg != 'undefined' && cmp.__defaultProperty) {
                    functionName = cmp.getSetterName(cmp.__defaultProperty);
                    cmp[functionName](cfg);
                }
                return this;
            };
            /**
             * Get property value by name
             * @param {String} propertyName
             * @returns {Mixed}
             */
            BaseClass.prototype.get = function (propertyName) {
                var functionName = this.getGetterName(propertyName);
                if (typeof this[functionName] != 'undefined') {
                    return this[functionName]();
                }
                econda.debug.error('Cannot get ' + propertyName + ' in ' + this._getClassName() + ': no getter defined.');
            };
            /**
             * get name of class. This will fail on older browsers and is intended for debug logging only
             * @private
             * @returns {String}
             */
            BaseClass.prototype._getClassName = function () {
                try {
                    return this.constructor.name;
                }
                catch (e) {
                    return null;
                }
            };
            /**
             * 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
             */
            BaseClass.prototype.getSetterName = function (propertyName) {
                return "set" + propertyName.substr(0, 1).toUpperCase() + propertyName.substr(1);
            };
            /**
             * Converts property names to setter function names
             * myProperty => getMyProperty
             *
             * @method
             * @private
             * @param {String} propertyName Name of class property
             * @return {String} Name of getter function for given property
             */
            BaseClass.prototype.getGetterName = function (propertyName) {
                return "get" + propertyName.substr(0, 1).toUpperCase() + propertyName.substr(1);
            };
            /**
             * Helper function to set objects to an array. Will use data as constructor argument if data is not an instance of given type.
             */
            BaseClass.prototype.setArray = function (fieldName, data, type, options) {
                if (type === void 0) { type = null; }
                this[fieldName] = [];
                this.addArray(fieldName, data, type, options);
                return this;
            };
            /**
             * Helper function to add objects to an array. Will use data as constructor argument if data is not an instance of given type.
             * @param {String} fieldName
             * @param {Mixed} data instance or config
             * @param {Function} type Reference to class
             * @param {Function} callback=null
             */
            BaseClass.prototype.addArray = function (fieldName, data, type, options) {
                if (type === void 0) { type = null; }
                if (typeof options === 'undefined' || options === null) {
                    options = {};
                }
                var collection = data;
                if (econda.util.ArrayUtils.isArray(data) == false) {
                    collection = [data];
                }
                for (var n = 0; n < collection.length; n++) {
                    var input;
                    var item;
                    if (typeof options.itemFilter === 'function') {
                        input = options.itemFilter.call(this, collection[n]);
                    }
                    else {
                        input = collection[n];
                    }
                    if (type === null || input instanceof type) {
                        item = input;
                    }
                    else {
                        item = (new type(input));
                    }
                    if (typeof options.callback === 'function') {
                        options.callback.call(this, item);
                    }
                    this[fieldName].push(item);
                }
                return this;
            };
            /**
             * Create a clone of current instance.
             * @returns {Object}
             */
            BaseClass.prototype.clone = function () {
                var ret = new this.constructor();
                for (var key in this) {
                    ret[key] = this[key];
                }
                return ret;
            };
            return BaseClass;
        }());
        base.BaseClass = BaseClass; // end of class
    })(base = econda.base || (econda.base = {}));
})(econda || (econda = {})); // end of module