/// <reference path="../collection/List.ts" />
/// <reference path="../util/Json.ts" />
/// <reference path="../env/LocalStorage.ts" />
/// <reference path="../env/SessionStorage.ts" />
/// <reference path="./Session.ts" />
/// <reference path="./ITouchpoint.ts" />
/// <reference path="./TouchpointType.ts" />
/// <reference path="./cleanup/ICleanupProcessor.ts" />
/// <reference path="./cleanup/DefaultProcessor.ts" />
/// <reference path="./collector/VisitStartCollector.ts" />
/// <reference path="./provisioning/Provisioner.ts" />
/// <reference path="./provisioning/IOrderInformation.ts" />
var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var econda;
(function (econda) {
    var tpm;
    (function (tpm) {
        var List = econda.collection.List;
        var JsonUtils = econda.util.Json;
        var storage = econda.env.LocalStorage;
        var sessionStorage = econda.env.SessionStorage;
        var Session = econda.tpm.Session;
        var TouchpointType = econda.tpm.TouchpointType;
        var DefaultProcessor = econda.tpm.cleanup.DefaultProcessor;
        var ArrayUtils = econda.util.ArrayUtils;
        var Provisioner = econda.tpm.provisioning.Provisioner;
        /**
         * Stores all user touchpoints in browser.
         *
         * @experimental
         * @class econda.tpm.Store
         */
        var Store = (function (_super) {
            __extends(Store, _super);
            function Store(instanceName) {
                _super.call(this);
                this._storageKey = null;
                this._isProtected = null;
                /**
                 * List of processors to remove outdated touchpoints
                 * @property {econda.collection.List) cleanupProcessors
                 */
                this.cleanupProcessors = null;
                this._storageKey = 'ec_tpm_' + instanceName;
                // initialize cleanup processors
                this.cleanupProcessors = new List({
                    items: [new DefaultProcessor()]
                });
                // load data
                this.load();
                this._executeCollectors();
            }
            Store.prototype.getStorageKey = function () {
                return this._storageKey;
            };
            /**
             * If store is protected, all new touchpoints will be marked as "irgnored".
             *
             * @param isProtected
             */
            Store.prototype.protect = function (isProtected) {
                if (isProtected === void 0) { isProtected = true; }
                this._isProtected = isProtected;
                if (isProtected) {
                    sessionStorage.setItem(this.getStorageKey() + '_protected', (new Date()).toISOString());
                }
                else {
                    sessionStorage.removeItem(this.getStorageKey() + '_protected');
                }
            };
            /**
             * Unprotect store, see protect() for details
             */
            Store.prototype.unprotect = function () {
                this.protect(false);
            };
            /**
             * True if store is protected.
             * @returns {boolean}
             */
            Store.prototype.isProtected = function () {
                if (this._isProtected === null) {
                    this._isProtected = (sessionStorage.getItem(this.getStorageKey() + '_protected') != null);
                }
                return this._isProtected;
            };
            /**
             * Returns an instance of touchpoint store. Standard usage is to call this without an instance name and use the 'default' instance.
             * @static
             * @returns {econda.tpm.Store}
             */
            Store.getInstance = function (instanceName) {
                var iname = instanceName || 'default';
                if (typeof Store._instances[iname] === 'undefined') {
                    Store._instances[iname] = new Store(iname);
                }
                return Store._instances[iname];
            };
            /**
             * Run registered cleanup processors to remove old touchpoints from local storage
             */
            Store.prototype.cleanup = function () {
                var cmp = this;
                this.cleanupProcessors.forEach(function (processor) {
                    processor.clean(cmp._items);
                });
            };
            Store.prototype.add = function (touchpoint) {
                var tp;
                if (typeof touchpoint === 'string') {
                    tp = {
                        name: touchpoint,
                        "type": TouchpointType.campaign,
                        category: 'default'
                    };
                }
                else {
                    tp = touchpoint;
                }
                if (typeof tp.timestamp === 'undefined' || !(tp.timestamp instanceof Date)) {
                    tp.timestamp = new Date();
                }
                if (typeof tp.session === 'undefined') {
                    tp.session = Session.getStartTimestamp();
                }
                if (typeof tp['"default"'] === 'undefined') {
                    tp['"default"'] = false;
                }
                if (typeof tp.entrance === 'undefined') {
                    tp.entrance = Session.isFirstPageView();
                }
                if (this.isProtected()) {
                    tp.ignore = true;
                }
                if (tp['"default"'] == false && tp.entrance == true) {
                    this._removeDefaultTouchpoints(tp.session);
                }
                _super.prototype.add.call(this, tp);
                this.cleanup();
                this.save();
                return this;
            };
            /**
             * Clear all touchtpoints, remove protection and clear persistent storage.
             */
            Store.prototype.reset = function () {
                this.clear();
                this.protect(false);
                this.save();
            };
            /**
             * Removes default touch points set in current session
             * @private
             */
            Store.prototype._removeDefaultTouchpoints = function (sessionId) {
                ArrayUtils.remove(this._items, function (item) {
                    return (item['"default"'] == true && item.entrance && item.session == sessionId);
                });
            };
            /// load data from storage
            Store.prototype.load = function () {
                var items = storage.getItem(this._storageKey);
                try {
                    this._items = items ? JsonUtils.parse(items) : [];
                }
                catch (e) {
                    this._items = [];
                }
            };
            /// save list to storage
            Store.prototype.save = function () {
                storage.setItem(this._storageKey, JsonUtils.stringify(this._items));
            };
            Store.prototype._executeCollectors = function () {
                var collectors = [
                    new econda.tpm.collector.VisitStartCollector()
                ];
                var collectedTouchpoints = [];
                for (var i = 0; i < collectors.length; i++) {
                    collectedTouchpoints = collectedTouchpoints.concat(collectors[i].execute());
                }
                for (var tp in collectedTouchpoints) {
                    this.add(tp);
                }
            };
            Store.prototype.provision = function (cfg) {
                if (cfg === void 0) { cfg = null; }
                return new Provisioner(cfg);
            };
            Store._instances = {};
            return Store;
        }(List));
        tpm.Store = Store;
    })(tpm = econda.tpm || (econda.tpm = {}));
})(econda || (econda = {}));
// provide shortcut function
econda['touchpoints'] = econda.tpm.Store.getInstance;