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 __());
};
/// <reference path="../../base/BaseClass.ts" />
/// <reference path="../../serialization/ISerializable.ts" />
/// <reference path="../../serialization/ISerializationInfo.ts" />
/// <reference path="../../util/ArrayUtils.ts" />
/// <reference path="../../env/SessionStorage.ts" />
/// <reference path="./IVisitorDataConfigOptions.ts" />
/// <reference path="../history/VisitorHistory.ts" />
/// <reference path="../../serialization/JsonSerializer.ts" />
var econda;
(function (econda) {
    var recengine;
    (function (recengine) {
        var visitor;
        (function (visitor) {
            var SessionStorage = econda.env.SessionStorage;
            /**
             * This is internal class used to store information about the current visitor. Use {@link econda.recengine.VisitorProfile} to access
             * visitor data.
             * @hide
             * @class econda.recengine.visitor.VisitorData
             */
            var VisitorData = (function (_super) {
                __extends(VisitorData, _super);
                function VisitorData(cfg) {
                    _super.call(this);
                    /**
                     * @cfg {Object} ids
                     * @accessor
                     */
                    this._ids = {};
                    /**
                     * @cfg {Object} properties
                     * @accessor
                     */
                    this._properties = {};
                    this._loginState = null;
                    this._history = null;
                    /**
                     * When in transaction, we must not save changes until commitTransaction is called
                     * @property {Boolean} [_isInTransaction=false]
                     * @private
                     */
                    this._isInTransaction = false;
                    this._triggerSaveTimeout = null;
                    if (cfg instanceof VisitorData) {
                        return cfg;
                    }
                    this.initConfig(cfg);
                }
                VisitorData.prototype.setId = function (typeOrDataObject, value) {
                    if (value === void 0) { value = null; }
                    if (typeof typeOrDataObject === 'string') {
                        this._ids[typeOrDataObject] = value;
                    }
                    else {
                        for (var idType in typeOrDataObject) {
                            this._ids[idType] = typeOrDataObject[idType];
                        }
                    }
                    this._triggerSaveIfNotInTransaction();
                    return this;
                };
                VisitorData.prototype.setIds = function (typeOrDataObject, value) {
                    if (value === void 0) { value = null; }
                    this.setId(typeOrDataObject, value);
                };
                VisitorData.prototype.getId = function (typeName) {
                    return this._ids[typeName] || null;
                };
                VisitorData.prototype.getIds = function () {
                    return this._ids;
                };
                VisitorData.prototype.clearIds = function () {
                    this._ids = {};
                    this._triggerSaveIfNotInTransaction();
                };
                VisitorData.prototype.getProperty = function (name) {
                    return this._properties[name] || null;
                };
                /**
                 * Set single property in client
                 */
                VisitorData.prototype.setProperty = function (nameOrDataObject, value) {
                    if (typeof nameOrDataObject === 'string') {
                        this._properties[nameOrDataObject] = value;
                    }
                    else if (typeof nameOrDataObject === 'object' && nameOrDataObject !== null) {
                        for (var propertyName in nameOrDataObject) {
                            this._properties[propertyName] = nameOrDataObject[propertyName];
                        }
                    }
                    this._triggerSaveIfNotInTransaction();
                };
                VisitorData.prototype.getProperties = function (name) {
                    if (typeof name === 'string') {
                        return this._properties[name] || null;
                    }
                    return this._properties;
                };
                VisitorData.prototype.setProperties = function (nameOrDataObject, value) {
                    if (value === void 0) { value = null; }
                    this.setProperty(nameOrDataObject, value);
                };
                VisitorData.prototype.clearProperties = function () {
                    this._properties = {};
                    this._triggerSaveIfNotInTransaction();
                };
                VisitorData.prototype.setLoginState = function (state) {
                    this._loginState = state;
                    this._triggerSaveIfNotInTransaction();
                };
                VisitorData.prototype.getLoginState = function () {
                    return this._loginState;
                };
                VisitorData.prototype.getHistory = function () {
                    return this._history;
                };
                VisitorData.prototype.setHistory = function (visitorHistory) {
                    var _this = this;
                    this._history = visitorHistory;
                    this._triggerSaveIfNotInTransaction();
                    if (this._history !== null) {
                        this._history.setOnChange(function (item) { return _this._triggerSaveIfNotInTransaction(); });
                    }
                };
                /**
                 * Do not save changes until we call commitTransaction manually
                 * @method
                 */
                VisitorData.prototype.beginTransaction = function () {
                    this._isInTransaction = true;
                };
                /**
                 * Save all changes (from last transaction)
                 * @method
                 */
                VisitorData.prototype.commitTransaction = function () {
                    this._isInTransaction = false;
                    this.saveInBrowser();
                };
                VisitorData.prototype._triggerSaveIfNotInTransaction = function () {
                    this._isInTransaction || this._triggerSaveInBrowser();
                };
                VisitorData.prototype._triggerSaveInBrowser = function () {
                    var cmp = this;
                    if (this._triggerSaveTimeout !== null) {
                        clearTimeout(this._triggerSaveTimeout);
                    }
                    this._triggerSaveTimeout = setTimeout(function () {
                        cmp.saveInBrowser();
                    }, 50);
                };
                /**
                 * Save to local storage
                 */
                VisitorData.prototype.saveInBrowser = function () {
                    if (this._triggerSaveTimeout !== null) {
                        clearTimeout(this._triggerSaveTimeout);
                    }
                    var s = new econda.serialization.JsonSerializer();
                    SessionStorage.setItem(VisitorData.STORAGE_KEY, s.serialize(this));
                };
                /**
                 * Load data from local storage
                 */
                VisitorData.prototype.loadFromBrowser = function () {
                    if (this._triggerSaveTimeout !== null) {
                        clearTimeout(this._triggerSaveTimeout);
                    }
                    var s = new econda.serialization.JsonSerializer();
                    var item = SessionStorage.getItem(VisitorData.STORAGE_KEY);
                    if (item) {
                        s.deserialize(item, this);
                    }
                };
                /**
                 * Get data for serialization
                 */
                VisitorData.prototype.getObjectData = function () {
                    return {
                        className: 'econda.recengine.visitor.VisitorData',
                        data: {
                            ids: this._ids,
                            properties: this._properties,
                            loginState: this._loginState,
                            history: this._history
                        }
                    };
                };
                /**
                 * Set data on deserialization
                 */
                VisitorData.prototype.setObjectData = function (data) {
                    if (typeof data === 'object' && data !== null) {
                        if (typeof data.properties === 'object' && data.properties !== null) {
                            this._properties = data.properties;
                        }
                        if (typeof data.ids === 'object' && data.ids !== null) {
                            this._ids = data.ids;
                        }
                        if (typeof data.loginState !== 'undefined') {
                            this._loginState = data.loginState;
                        }
                        if (typeof data.history !== 'undefined') {
                            this.setHistory(data.history);
                        }
                    }
                };
                VisitorData.STORAGE_KEY = 'econda.recengine.VisitorData';
                return VisitorData;
            }(econda.base.BaseClass));
            visitor.VisitorData = VisitorData;
        })(visitor = recengine.visitor || (recengine.visitor = {}));
    })(recengine = econda.recengine || (econda.recengine = {}));
})(econda || (econda = {}));