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/JsonSerializer.ts" />
/// <reference path="./PageView.ts" />
var econda;
(function (econda) {
    var env;
    (function (env) {
        var JsonSerializer = econda.serialization.JsonSerializer;
        var CookieStore = econda.cookie.Store;
        /**
         * Represents a browser session.
         * @class econda.env.Session
         * @experimental
         */
        var Session = (function (_super) {
            __extends(Session, _super);
            function Session(cfg) {
                _super.call(this);
                /**
                 * Date and time of session start
                 * @property {Date} startDate
                 */
                this._startDate = null;
                this._history = [];
                if (cfg instanceof Session) {
                    return cfg;
                }
                this.initConfig(cfg);
            }
            /**
             * True if this features is supported in current browser
             * @returns {boolean}
             */
            Session.isSupported = function () {
                if (typeof window.sessionStorage === 'undefined') {
                    return false;
                }
                var result = null;
                try {
                    window.sessionStorage.setItem('ectest', 'ok');
                    result = window.sessionStorage.getItem('ectest');
                }
                finally {
                    return (result == 'ok');
                }
            };
            Session.prototype.getStartDate = function () {
                return this._startDate;
            };
            Session.prototype.getPageViewCount = function () {
                return this.getHistory().length;
            };
            Session.prototype.getHistory = function () {
                return this._history;
            };
            Session.getId = function () {
                var keySessionID = 'emos_jcsid';
                var sessionId = null;
                var samplingRate = 1;
                // Check EMOS3
                if (window["emos3"] !== null) {
                    sessionId = emos3.emos_sid;
                }
                // Check LocalStorage
                if (sessionId === null) {
                    var sessionValue = env.SessionStorage.getItem(keySessionID);
                    if (sessionValue !== null) {
                        sessionId = sessionValue.split(':', 2)[0];
                    }
                }
                // Check Cookie
                if (sessionId === null) {
                    var sessionValue = CookieStore.getValue(keySessionID);
                    if (sessionValue !== null) {
                        sessionId = sessionValue.split(':', 2)[0];
                    }
                }
                // Fallback - generate Session ID
                if (sessionId === null) {
                    sessionId = this.generateId();
                    if (window["emos3"] !== null) {
                        emos3.emos_sid = sessionId;
                    }
                    var segments = [
                        sessionId,
                        't',
                        samplingRate,
                        0
                    ];
                    env.SessionStorage.setItem(keySessionID, segments.join(':'));
                }
                return sessionId;
            };
            Session.prototype.getObjectData = function () {
                return {
                    className: 'econda.env.Session',
                    data: {
                        startDate: this._startDate,
                        history: this._history
                    }
                };
            };
            Session.prototype.setObjectData = function (data) {
                this._startDate = data.startDate || null;
                this._history = data.history || [];
            };
            Session.prototype.init = function () {
                this._loadFromSessionStorage();
                if (this._startDate === null) {
                    this._initNewSession();
                }
                this._addCurrentPageView();
                this._saveToSessionStorage();
            };
            Session.prototype._initNewSession = function () {
                this._startDate = new Date();
            };
            Session.prototype._loadFromSessionStorage = function () {
                var data = window.sessionStorage.getItem('econda.env.Session');
                if (data) {
                    JsonSerializer.deserialize(data, this);
                    return true;
                }
                else {
                    return false;
                }
            };
            Session.prototype._saveToSessionStorage = function () {
                window.sessionStorage.setItem('econda.env.Session', JsonSerializer.serialize(this));
            };
            Session.prototype._addCurrentPageView = function () {
                var pv = new econda.env.PageView({
                    timestamp: new Date(),
                    uri: document.location.href
                });
                this._history.push(pv);
                return this;
            };
            Session.generateId = function () {
                var time = new Date().getTime();
                var time0 = time & 0xFFFFFFFF;
                var time1 = (time / 0x100000000) & 0xFFFFFFFF;
                var b = [];
                b.push(time1 >>> 8 & 0xFF);
                b.push(time1 & 0xFF);
                b.push(time0 >>> 24);
                b.push(time0 >>> 16 & 0xFF);
                b.push(time0 >>> 8 & 0xFF);
                b.push(time0 & 0xFF);
                for (var i = 0; i < 9; i++) {
                    var r = 0x10000 * Math.random();
                    b.push(r >>> 8 & 0xFF);
                    b.push(r & 0xFF);
                }
                var ua = navigator.userAgent;
                if (ua) {
                    for (var j = 0; j < ua.length; j++) {
                        var pos = 6 + (j % 18);
                        b[pos] = (b[pos] ^ ua.charCodeAt(j)) & 0xFF;
                    }
                }
                return this._b64d2t(b);
            };
            Session._b64d2t = function (d) {
                var base64s = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*_';
                var b64 = base64s;
                var r = [];
                var i = 0;
                var dl = d.length;
                // this is for the padding
                if ((dl % 3) === 1) {
                    d.push(0);
                    d.push(0);
                }
                else if ((dl % 3) === 2)
                    d.push(0);
                var dl2 = d.length;
                while (i < dl2) {
                    r.push(b64.charAt(d[i] >> 2));
                    r.push(b64.charAt(((d[i] & 3) << 4) | (d[i + 1] >> 4)));
                    r.push(b64.charAt(((d[i + 1] & 15) << 2) | (d[i + 2] >> 6)));
                    r.push(b64.charAt(d[i + 2] & 63));
                    i += 3;
                }
                // this is again for the padding
                if ((dl % 3) === 1)
                    r[r.length - 1] = r[r.length - 2] = "";
                if ((dl % 3) === 2)
                    r[r.length - 1] = "";
                // we join the array to return a textstring
                return r.join("");
            };
            return Session;
        }(econda.base.BaseClass));
        env.Session = Session;
    })(env = econda.env || (econda.env = {}));
})(econda || (econda = {}));