var uniflash;
(function (uniflash) {
    var session;
    (function (session) {
        'use strict';
        var SavedSessionData = (function () {
            function SavedSessionData() {
                this.version = SavedSessionData.CURRENT_VERSION;
                this.ccxmlContent = null;
                this.deviceXMLFile = null;
                this.connectionXMLFile = null;
                this.queryConfig = {
                    cores: [],
                    debuggableCores: [],
                    nondebuggableCores: [],
                    deviceXMLFile: '',
                    connectionXMLFile: ''
                };
            }
            SavedSessionData.CURRENT_VERSION = 'uniflash_session_format_version_2';
            return SavedSessionData;
        }());
        var SessionState;
        (function (SessionState) {
            SessionState[SessionState["RefreshStarted"] = 1] = "RefreshStarted";
            SessionState[SessionState["RefreshCompleted"] = 2] = "RefreshCompleted";
            SessionState[SessionState["LoadStarted"] = 3] = "LoadStarted";
            SessionState[SessionState["LoadCompleted"] = 4] = "LoadCompleted";
            SessionState[SessionState["Unitialized"] = 5] = "Unitialized";
            SessionState[SessionState["Initialized"] = 6] = "Initialized";
        })(SessionState || (SessionState = {}));
        var SessionService = (function () {
            function SessionService($q, $window, $state, $rootScope, $log, ticFileDialogs, ticFileFactory, ticAlerts, ticExecutionPlatform, ufPropertiesDB, ufTargetConfig, ufPreferencesSrv, ufConsole) {
                var _this = this;
                this.$q = $q;
                this.$window = $window;
                this.$state = $state;
                this.$rootScope = $rootScope;
                this.$log = $log;
                this.ticFileDialogs = ticFileDialogs;
                this.ticFileFactory = ticFileFactory;
                this.ticAlerts = ticAlerts;
                this.ticExecutionPlatform = ticExecutionPlatform;
                this.ufPropertiesDB = ufPropertiesDB;
                this.ufTargetConfig = ufTargetConfig;
                this.ufPreferencesSrv = ufPreferencesSrv;
                this.ufConsole = ufConsole;
                // service data
                // that needs to be saved and loaded as part of the session
                this.data = new SavedSessionData();
                /* Used to facilatite saving state whent he page reloads*/
                this.saveToBrowserSessionStorage = function () {
                    var isMainPage = _this.$state.current.name.split(".")[0] === "main";
                    if (SessionState.Unitialized !== _this.getState() && isMainPage) {
                        var dataToSave = _this.saveSession();
                        _this.updateState(SessionState.RefreshStarted);
                        _this.$window.sessionStorage.setItem(SessionService.browserSessionStorageKey, JSON.stringify(dataToSave));
                    }
                };
                this.sessionDataStore = new session.SessionDataStore();
                // before leaving the page save data to a session storage 
                this.$window.onbeforeunload = this.saveToBrowserSessionStorage;
            }
            SessionService.prototype.openDialogIfNeeded = function (selections) {
                if (selections) {
                    return this.$q.resolve(selections);
                }
                else {
                    return this.ticFileDialogs.openFile(SessionService.openSessionDialogTitle, SessionService.sessionFileExt, SessionService.sessionFileType);
                }
            };
            SessionService.prototype.saveCurrentSessionToFile = function (sessionFile) {
                var dataToSave = this.saveSession();
                return sessionFile.setContents(JSON.stringify(dataToSave));
            };
            SessionService.prototype.saveSession = function () {
                this.$log.debug('session service: saveSession() ');
                this.sessionDataStore.updateBeforeSave();
                this.$log.debug('session service: saveSession() 2');
                var dataToSave = this.sessionDataStore.getSessionDataAll();
                this.$log.debug('session service: saveSession() dataToSave: ' + JSON.stringify(dataToSave));
                // addtionally add our own data to be saved
                dataToSave.session = this.data;
                this.$log.debug('session service: saveSession() this.data: ' + JSON.stringify(this.data));
                return dataToSave;
            };
            SessionService.prototype.registerSessionDataProvider = function (key, provider) {
                this.sessionDataStore.registerSessionDataProvider(key, provider);
                //when some provider is registered, update initial data again
                this.sessionDataStrAtStart = angular.toJson(this.saveSession());
            };
            SessionService.prototype.createNewSession = function (deviceXMLFile, connectionXMLFile, lp) {
                var _this = this;
                if (lp === void 0) { lp = false; }
                var ccxmlContent;
                return this.ufTargetConfig.createCCXML(deviceXMLFile, connectionXMLFile, lp)
                    .then(function (newCCXMLContent) {
                    ccxmlContent = newCCXMLContent;
                    return _this.ufTargetConfig.queryConfig(ccxmlContent);
                })
                    .then(function (queryConfig) {
                    // set our internal data;
                    _this.data.deviceXMLFile = deviceXMLFile;
                    _this.data.connectionXMLFile = connectionXMLFile;
                    _this.data.ccxmlContent = ccxmlContent;
                    _this.removeUnwantedCores(queryConfig.cores);
                    _this.data.queryConfig = queryConfig;
                    // wipe out the stored session data
                    _this.sessionDataStore.setSessionDataAll({});
                    // notify everyone a new session is has been loaded
                    _this.sessionDataStore.sessionLoaded();
                    _this.sessionName = _this.data.deviceXMLFile;
                    return _this.ufTargetConfig.getDevice(deviceXMLFile);
                })
                    .then(function (device) {
                    return _this.ufPropertiesDB.getPropertiesData(_this.data.queryConfig);
                })
                    .finally(function () {
                    _this.sessionDataStrAtStart = angular.toJson(_this.saveSession());
                });
            };
            // start a new session if needed
            SessionService.prototype.startIfNeeded = function (deviceXMLFile, connectionXMLFile, force, lp) {
                var _this = this;
                if (lp === void 0) { lp = false; }
                var currentState = force ? SessionState.Unitialized : this.getState();
                if (!this.sessionName) {
                    this.sessionName = deviceXMLFile;
                }
                switch (currentState) {
                    case SessionState.RefreshStarted:
                        this.updateState(SessionState.RefreshCompleted);
                        var browserSessiontDataToLoad = this.$window.sessionStorage.getItem(SessionService.browserSessionStorageKey);
                        this.initPromise = this.loadData(JSON.parse(browserSessiontDataToLoad)).catch(function (e) {
                            return _this.ticAlerts.showError('Failed to load session data from browser storage : ' + e.message);
                        });
                        break;
                    case SessionState.LoadStarted:
                        this.initPromise = this.$q.resolve();
                        this.updateState(SessionState.LoadCompleted);
                    case SessionState.LoadCompleted:
                    case SessionState.RefreshCompleted:
                        this.updateState(SessionState.Initialized);
                        break;
                    default:
                        this.initPromise = this.createNewSession(deviceXMLFile, connectionXMLFile, lp)
                            .then(function () {
                            _this.updateState(SessionState.Initialized);
                        });
                        break;
                }
                return this.initPromise;
            };
            SessionService.prototype.isG2DeviceSpecialHandling = function (deviceId) {
                var OSType = TICloudAgent.getOS();
                var isG2Device = /.*MSP.*G2.*/.test(deviceId);
                return (OSType !== 'win') && isG2Device;
            };
            SessionService.prototype.loadData = function (sessionData) {
                var _this = this;
                this.sessionDataStore.setSessionDataAll(sessionData);
                this.data = this.sessionDataStore.getSessionDataAll().session;
                return this.ufPropertiesDB.getPropertiesData(this.data.queryConfig)
                    .then(function () {
                    _this.sessionDataStore.sessionLoaded();
                    // session update the state
                    _this.$state.go('main.Program', {
                        deviceXMLFile: _this.data.deviceXMLFile,
                        connectionXMLFile: _this.data.connectionXMLFile
                    }, {
                        inherit: false,
                        reload: true
                    });
                });
            };
            SessionService.prototype.newFromCCXML = function (deviceXMLFile, connectionXMLFile, ccxmlContent) {
                var _this = this;
                this.updateState(SessionState.LoadStarted);
                return this.ufTargetConfig.queryConfig(ccxmlContent)
                    .then(function (queryConfig) {
                    // set our internal data;
                    _this.data.deviceXMLFile = deviceXMLFile;
                    _this.data.connectionXMLFile = connectionXMLFile;
                    _this.data.ccxmlContent = ccxmlContent;
                    _this.removeUnwantedCores(queryConfig.cores);
                    _this.data.queryConfig = queryConfig;
                    // wipe out the stored session data
                    _this.sessionDataStore.setSessionDataAll({});
                    // notify everyone a new session is has been loaded
                    _this.sessionDataStore.sessionLoaded();
                    _this.sessionName = _this.data.deviceXMLFile;
                    return _this.ufTargetConfig.getDevice(deviceXMLFile);
                })
                    .then(function (device) {
                    return _this.ufPropertiesDB.getPropertiesData(_this.data.queryConfig);
                })
                    .finally(function () {
                    _this.sessionDataStrAtStart = angular.toJson(_this.saveSession());
                });
            };
            SessionService.prototype.load = function (selections) {
                var _this = this;
                this.$log.debug('session service: load()');
                var sessionFile;
                var confirmPromise = this.initPromise ? this.confirmLeave() : this.$q.resolve('No session to save');
                return confirmPromise.then(function () {
                    return _this.openDialogIfNeeded(selections).then(function (selections) {
                        sessionFile = selections[0];
                        return _this.ufPreferencesSrv.pushRecentSessionFile(sessionFile);
                    }).then(function () {
                        return sessionFile.getContents();
                    }).then(function (contents) {
                        return _this.updateSessionDataIfNeeded(JSON.parse(contents));
                    }).then(function (sessionData) {
                        if (!_this.isG2DeviceSpecialHandling(sessionData.session.deviceXMLFile)) {
                            _this.sessionFile = sessionFile;
                            _this.updateState(SessionState.LoadStarted);
                            _this.sessionName = sessionFile.name.slice(0, -9);
                            return _this.loadData(sessionData);
                        }
                        else {
                            throw { message: 'G2 Devices are only supported on Windows.' };
                        }
                    }).catch(function (e) {
                        if ((e !== 'No') && (e !== 'Cancel Clicked') && (e !== 'escape key press') && (e !== 'backdrop click')) {
                            var msg = 'Load session failed : ' + e.message;
                            return _this.ticAlerts.showError(msg);
                        }
                    }).finally(function () {
                        _this.sessionDataStrAtStart = angular.toJson(_this.saveSession());
                    });
                });
            };
            SessionService.prototype.updateSessionDataIfNeeded = function (sessionData) {
                var _this = this;
                return this.$q.resolve(this.isOldSession(sessionData.session.version))
                    .then(function (isNeedUpdate) {
                    if (isNeedUpdate) {
                        return _this.$q.resolve(_this.ticExecutionPlatform.getPlatform() === ti_common.PlatformType.NW)
                            .then(function (isNW) {
                            if (isNW) {
                                return _this.ticAlerts.showConfirm('Update Session File to Continue', 'Your session file is of an older version and needs to be updated to work with this version of the tool. Updating the session file may cause it to stop working on an older version of UniFlash.');
                            }
                        })
                            .then(function () {
                            return _this.updateSessionData(sessionData);
                        });
                    }
                    else {
                        return sessionData;
                    }
                });
            };
            SessionService.prototype.isOldSession = function (ver) {
                if (!ver) {
                    return true;
                }
                //custom logic to determine which is newer, right now just compare the last digit in the version str
                var fileVerNum = parseInt(ver.substring(ver.lastIndexOf('_') + 1));
                var curVerNum = parseInt(SavedSessionData.CURRENT_VERSION.substring(SavedSessionData.CURRENT_VERSION.lastIndexOf('_') + 1));
                return curVerNum > fileVerNum;
            };
            SessionService.prototype.updateSessionData = function (data) {
                var ret = data;
                //TODO: all session file update logic goes here
                //update the structure of session data as needed
                return ret;
            };
            SessionService.prototype.new = function () {
                this.$log.debug('session service: new()');
                this.saveToBrowserSessionStorage();
                this.$state.go('welcome');
            };
            SessionService.prototype.getCCXML = function () {
                return this.data.ccxmlContent;
            };
            SessionService.prototype.getDeviceXMLFile = function () {
                return this.data.deviceXMLFile;
            };
            SessionService.prototype.getConnectionXMLFile = function () {
                return this.data.connectionXMLFile;
            };
            SessionService.prototype.save = function () {
                var _this = this;
                this.$log.debug('session service: save() 1');
                return this.ticFileDialogs.saveFile(SessionService.saveSessionDialogTitle, this.sessionName, SessionService.sessionFileExt)
                    .then(function (newSessionFile) {
                    _this.sessionFile = newSessionFile;
                    _this.$log.debug('session service: save() sessionFile: ' + _this.sessionFile);
                    _this.sessionName = newSessionFile.name.slice(0, -9);
                    _this.$log.debug('session service: save() sessionName: ' + _this.sessionName);
                    return _this.ufPreferencesSrv.pushRecentSessionFile(_this.sessionFile);
                })
                    .then(function () {
                    _this.$log.debug('session service: save() 2');
                    return _this.saveCurrentSessionToFile(_this.sessionFile);
                })
                    .then(function () {
                    _this.$log.debug('session service: save() 3');
                    _this.sessionDataStrAtStart = angular.toJson(_this.saveSession());
                    _this.$log.debug('session service: save() 4');
                })
                    .catch(function (e) {
                    _this.$log.debug('session service: save() Error in saving file: ' + e.message);
                });
            };
            SessionService.prototype.saveToTempSession = function () {
                var dataToSave = this.sessionDataStore.getSessionDataAll();
                if (dataToSave.session && dataToSave.session.ccxmlContent) {
                    var fileNameWithExt = 'unsaved session' + SessionService.sessionFileExt;
                    var file = this.ticFileFactory.create(fileNameWithExt);
                    return this.saveCurrentSessionToFile(file);
                }
                else {
                    return this.$q.when('');
                }
            };
            SessionService.prototype.queryConfig = function () {
                return this.data.queryConfig;
            };
            SessionService.prototype.confirmLeave = function () {
                var _this = this;
                this.ufConsole.clearMessages();
                var oldData = this.sessionDataStrAtStart;
                var newData = angular.toJson(this.saveSession());
                if (oldData === newData) {
                    return this.$q.resolve('');
                }
                else {
                    return this.ticAlerts.showConfirm('Are you sure?', 'Unsaved session changes will be lost!').then(function () {
                        _this.initPromise = null;
                        _this.updateState(SessionState.Unitialized);
                    });
                }
            };
            SessionService.prototype.updateState = function (newState) {
                this.$window.sessionStorage.setItem('state', JSON.stringify(newState));
                if (newState === SessionState.LoadCompleted || newState === SessionState.Initialized) {
                    this.$rootScope.$emit('session.configured');
                }
            };
            SessionService.prototype.getState = function () {
                var newState = JSON.parse(this.$window.sessionStorage.getItem('state'));
                return newState ? newState : SessionState.Unitialized;
            };
            SessionService.prototype.removeUnwantedCores = function (coreList) {
                this.removeCore(coreList, 'C67');
                this.removeCore(coreList, 'CSETB');
            };
            SessionService.prototype.removeCore = function (coreList, coreName) {
                var index = _.findIndex(coreList, function (core) {
                    return (core.name.substring(0, coreName.length) === coreName);
                });
                if (index !== -1) {
                    coreList.splice(index, 1);
                }
            };
            SessionService.prototype.isSerial = function () {
                return (this.data.queryConfig.connectionXMLFile.indexOf('Serial_Connection') !== -1);
            };
            SessionService.browserSessionStorageKey = 'uniflash_temp_session';
            SessionService.sessionFileExt = '.uniflash';
            SessionService.sessionFileType = 'Sessions';
            SessionService.saveSessionDialogTitle = 'Enter your UniFlash session name';
            SessionService.openSessionDialogTitle = 'Load UniFlash session';
            SessionService.$inject = ['$q', '$window', '$state', '$rootScope', '$log',
                'ticFileDialogs', 'ticFileFactory', 'ticAlerts', 'ticExecutionPlatform',
                'ufPropertiesDB', 'ufTargetConfig', 'ufPreferencesSrv', 'ufConsole'];
            return SessionService;
        }());
        session.SessionService = SessionService;
        angular.module('uniflash').service('ufSession', SessionService);
    })(session = uniflash.session || (uniflash.session = {}));
})(uniflash || (uniflash = {}));
