"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var HaikuGlobal_1 = require("./HaikuGlobal");
exports.GLOBAL_LISTENER_KEY = '*';
exports.GENERIC_EVENT_KEY = 'event';
var upperCaseFirstLetter = function (str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
};
var camelize = function (str) {
    return str.replace(/\W+/g, ' ').replace(/(?:^\w|[A-Z]|\b\w)/g, function (letter, index) {
        return (index === 0) ? letter.toLowerCase() : letter.toUpperCase();
    }).replace(/\s+/g, '');
};
var upsertInstanceRegistry = function (className) {
    if (!HaikuGlobal_1.default.models[className]) {
        HaikuGlobal_1.default.models[className] = [];
    }
    return HaikuGlobal_1.default.models[className];
};
var addInstanceToGlobalModelRegistry = function (instance) {
    var className = instance.getClassName();
    var instanceRegistry = upsertInstanceRegistry(className);
    return instanceRegistry.push(instance);
};
var addValueToGlobalCache = function (key, value) {
    HaikuGlobal_1.default.cache[key] = value;
};
var retrieveValueFromGlobalCache = function (key) {
    return HaikuGlobal_1.default.cache[key];
};
var clearMatchingPropertiesInGlobalCache = function (matcher) {
    for (var key in HaikuGlobal_1.default.cache) {
        if (key.indexOf(matcher) !== -1) {
            delete HaikuGlobal_1.default.cache[key];
        }
    }
};
var clearAllCaches = function () {
    for (var key in HaikuGlobal_1.default.cache) {
        delete HaikuGlobal_1.default.cache[key];
    }
};
var HaikuBase = (function () {
    function HaikuBase() {
        this.$id = addInstanceToGlobalModelRegistry(this);
        this.listeners = {};
    }
    HaikuBase.prototype.getId = function () {
        return this.$id;
    };
    HaikuBase.prototype.getRegistryIndex = function () {
        return this.getId() - 1;
    };
    HaikuBase.prototype.getPrimaryKey = function () {
        return this.getClassName() + ":" + this.getId();
    };
    HaikuBase.prototype.getClassName = function () {
        return this.constructor['name'];
    };
    HaikuBase.prototype.buildQualifiedCacheKey = function (key) {
        return this.getPrimaryKey() + ":" + key;
    };
    HaikuBase.prototype.cacheSet = function (key, value) {
        addValueToGlobalCache(this.buildQualifiedCacheKey(key), value);
    };
    HaikuBase.prototype.cacheGet = function (key) {
        return retrieveValueFromGlobalCache(this.buildQualifiedCacheKey(key));
    };
    HaikuBase.prototype.cacheFetch = function (key, provider) {
        var valueExisting = this.cacheGet(key);
        if (valueExisting !== undefined) {
            return valueExisting;
        }
        var valueProvided = provider();
        this.cacheSet(key, valueProvided);
        return valueProvided;
    };
    HaikuBase.prototype.cacheUnset = function (key) {
        addValueToGlobalCache(this.buildQualifiedCacheKey(key), undefined);
    };
    HaikuBase.prototype.cacheClear = function () {
        clearMatchingPropertiesInGlobalCache(this.getPrimaryKey());
    };
    HaikuBase.prototype.subcacheGet = function (key) {
        return this.cacheGet(key);
    };
    HaikuBase.prototype.subcacheEnsure = function (key) {
        if (!this.cacheGet(key)) {
            this.cacheSet(key, {});
        }
    };
    HaikuBase.prototype.subcacheClear = function (key) {
        this.cacheSet(key, {});
    };
    HaikuBase.prototype.on = function (key, listener) {
        if (!this.listeners[key]) {
            this.listeners[key] = [];
        }
        this.listeners[key].push(listener);
    };
    HaikuBase.prototype.addEventListener = function (key, listener) {
        this.on(key, listener);
    };
    HaikuBase.prototype.off = function (key, listener) {
        if (!this.listeners[key]) {
            return;
        }
        for (var i = this.listeners[key].length - 1; i >= 0; i--) {
            if (this.listeners[key][i] === listener) {
                this.listeners[key].splice(i, 1);
            }
        }
    };
    HaikuBase.prototype.removeEventListener = function (key, listener) {
        this.off(key, listener);
    };
    HaikuBase.prototype.removeListener = function (key, listener) {
        this.off(key, listener);
    };
    HaikuBase.prototype.emitToListeners = function (key, args) {
        if (this.listeners[key]) {
            for (var i = 0; i < this.listeners[key].length; i++) {
                this.listeners[key][i].apply(null, args);
            }
        }
    };
    HaikuBase.prototype.emitToGenericListeners = function (key, args) {
        if (this.listeners[exports.GLOBAL_LISTENER_KEY]) {
            for (var i = 0; i < this.listeners[exports.GLOBAL_LISTENER_KEY].length; i++) {
                this.listeners[exports.GLOBAL_LISTENER_KEY][i].apply(null, [key].concat(args));
            }
        }
    };
    HaikuBase.prototype.emit = function (key) {
        var args = [];
        for (var _i = 1; _i < arguments.length; _i++) {
            args[_i - 1] = arguments[_i];
        }
        this.emitToListeners(key, args);
        this.emitToConfigHandlers(key, args);
        this.emitToGenericListeners(key, args);
        var allArgs = [key].concat(args);
        this.emitToConfigHandlers(exports.GENERIC_EVENT_KEY, allArgs);
    };
    HaikuBase.prototype.emitToConfigHandlers = function (key, args) {
        if (!this.config) {
            return;
        }
        var keyCamelCase = this.cacheFetch(key, function () {
            return upperCaseFirstLetter(camelize(key));
        });
        var keyCamelCaseWithOnPrefix = "on" + keyCamelCase;
        if (typeof this.config[keyCamelCaseWithOnPrefix] === 'function') {
            this.config[keyCamelCaseWithOnPrefix].apply(null, args);
        }
        var keyCamelCaseWithOnHaikuPrefix = "onHaiku" + keyCamelCase;
        if (typeof this.config[keyCamelCaseWithOnHaikuPrefix] === 'function') {
            this.config[keyCamelCaseWithOnHaikuPrefix].apply(null, args);
        }
    };
    return HaikuBase;
}());
exports.default = HaikuBase;
HaikuBase['getRegistryForClass'] = function (klass) {
    return upsertInstanceRegistry(klass.name);
};
//# sourceMappingURL=HaikuBase.js.map