"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var State_1 = require("./State");
/** Class that creates a key from the id (ignoring the current state of the component. */
var ComponentIdKeyGenerator = /** @class */ (function () {
    function ComponentIdKeyGenerator() {
    }
    ComponentIdKeyGenerator.prototype.key = function (id) {
        return generateHash(id);
    };
    return ComponentIdKeyGenerator;
}());
exports.ComponentIdKeyGenerator = ComponentIdKeyGenerator;
/** Class that creates a key for the id respecting the current transformation of the object.
 *  Thus using this class to generate keys for the same id after it has changed e.g. its position will result in different keys.
 */
var ComponentTransformationKeyGenerator = /** @class */ (function () {
    function ComponentTransformationKeyGenerator() {
    }
    ComponentTransformationKeyGenerator.prototype.key = function (id) {
        var tPosition = State_1.State.API.GetPosition(id);
        var tXRotation = State_1.State.API.GetXRotation(id);
        var tYRotation = State_1.State.API.GetYRotation(id);
        var tZRotation = State_1.State.API.GetZRotation(id);
        return generateHash(id + " + " + tPosition.x + " + " + tPosition.y + " + " + tPosition.z + " + " + tXRotation + " + " + tYRotation + " + " + tZRotation);
    };
    return ComponentTransformationKeyGenerator;
}());
exports.ComponentTransformationKeyGenerator = ComponentTransformationKeyGenerator;
/** Class that associates a component id with the corresponding local bounds. */
var IdBoundsAssociator = /** @class */ (function () {
    function IdBoundsAssociator() {
    }
    IdBoundsAssociator.prototype.getAssociate = function (id) {
        return State_1.State.API.GetBounds(id, "Local", true);
    };
    return IdBoundsAssociator;
}());
exports.IdBoundsAssociator = IdBoundsAssociator;
/**
 * Method for creating a hash (number) from a string.
 * Solution from http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery
 */
function generateHash(stringToHash) {
    var hash = 0;
    var chr = "";
    var len = stringToHash.length;
    if (len === 0) {
        return hash;
    }
    for (var i = 0; i < len; i++) {
        // js will convert from char to int
        chr = stringToHash.charCodeAt(i);
        hash = (hash << 5) - hash + chr;
        hash |= 0; // Convert to 32bit integer
    }
    return hash;
}
exports.generateHash = generateHash;
/** Abstract cache class. This cache takes a key generator and an associator.
 *  Values are saved and acquired via the first parameter (U). Cached values are of type T.
 *  E.g. if you want to implement a cache that saved the points of an object and access it by the objects id,
 *  you would need a key generator for the id (that gives an unique key depending on the state of the object) and
 *  an associator which will associate the id with the corresponding points.
 */
var Cache = /** @class */ (function () {
    /**
     * The constructor. Takes the generator and associator and initializes the empty internal cache.
     * @param generator: the generator
     * @param associator the associator
     */
    function Cache(generator, associator) {
        this.associator = associator;
        this.generator = generator;
        this.cache = {};
    }
    /**
     * Gets the cached value associated with the object.
     * @param obj
     * @returns The cached value if it exists, undefined otherwise.
     */
    Cache.prototype.get = function (obj) {
        var tKey = this.generator.key(obj);
        return this.cache[tKey] ? this.cache[tKey] : undefined;
    };
    /**
     * Saves the associated value of the object as a value in the cache, if there is no object matching the key.
     * Uses the generator and the associator
     * @param obj the object
     */
    Cache.prototype.put = function (obj) {
        var tKey = this.generator.key(obj);
        if (this.cache[tKey]) {
            return;
        }
        var tAssociated = this.associator.getAssociate(obj);
        this.cache[tKey] = tAssociated;
    };
    /**
     * Puts all associated values of the objects into the cache.
     * @param objects
     */
    Cache.prototype.putAll = function (objects) {
        var _this = this;
        objects.forEach(function (obj) { return _this.put(obj); });
    };
    /**
     * Empties the internal cache.
     */
    Cache.prototype.flush = function () {
        this.cache = {};
    };
    return Cache;
}());
exports.Cache = Cache;
/** Class that contains caches. */
var Caches = /** @class */ (function () {
    function Caches() {
    }
    /** Cache for the local bounds. */
    Caches.boundsCache = new Cache(new ComponentIdKeyGenerator(), new IdBoundsAssociator());
    return Caches;
}());
exports.Caches = Caches;
