var uniflash;
(function (uniflash) {
    'use strict';
    var DS = (function () {
        function DS($q, $rootScope, $log, ticAlerts, ufSession, ufPrograms, ufPropertiesValue, ufAgentInstallDialog, ufPreferencesSrv, ufContext, ufConsole, ufPropertiesDB, ufResets, ufTargetConfig, x2js) {
            var _this = this;
            this.$q = $q;
            this.$rootScope = $rootScope;
            this.$log = $log;
            this.ticAlerts = ticAlerts;
            this.ufSession = ufSession;
            this.ufPrograms = ufPrograms;
            this.ufPropertiesValue = ufPropertiesValue;
            this.ufAgentInstallDialog = ufAgentInstallDialog;
            this.ufPreferencesSrv = ufPreferencesSrv;
            this.ufContext = ufContext;
            this.ufConsole = ufConsole;
            this.ufPropertiesDB = ufPropertiesDB;
            this.ufResets = ufResets;
            this.ufTargetConfig = ufTargetConfig;
            this.x2js = x2js;
            this.modules = ['File', 'TargetSupport'];
            this.cachedConfigure = null;
            this.cachedConnectedCores = {}; //map
            this.targetStateListeners = {}; //map
            this.dsLogPath = null;
            this.dsLogName = null;
            this.runTargetAfterProgramLoadDisabled = false;
            this._ufResets = ufResets;
            this._q = $q;
            //listen for session launch here and change dsImpl accordingly
            $rootScope.$on('session.configured', function () {
                _this.partNum = _this.ufPropertiesDB.getPartnum();
                _this.$log.debug('ufDS, session.configured, partnum of current session = ' + _this.partNum);
                //factory base on the partnum
                _this.isJLink = (_this.ufSession.data
                    && _this.ufSession.data.connectionXMLFile
                    && (_this.ufSession.data.connectionXMLFile.toLowerCase().indexOf('j-link') !== -1));
                if (uniflash.DSLprfImpl.matches(_this.partNum) && !_this.isJLink && !_this.isSerial()) {
                    _this.dsImpl = new uniflash.DSLprfImpl(_this, _this.$q, _this.$rootScope, _this.$log, _this.ticAlerts, _this.ufSession, _this.ufPrograms, _this.ufPropertiesValue, _this.ufAgentInstallDialog, _this.ufPreferencesSrv, _this.ufContext, _this.ufTargetConfig, _this.ufConsole, _this.x2js);
                }
                else if (uniflash.DSDualCoreC28Impl.matches(_this.partNum) && !_this.isSerial()) {
                    _this.dsImpl = new uniflash.DSDualCoreC28Impl(_this, _this.$q, _this.$rootScope, _this.$log, _this.ticAlerts, _this.ufSession, _this.ufPrograms, _this.ufPropertiesValue, _this.ufAgentInstallDialog, _this.ufPreferencesSrv, _this.ufContext, _this.ufTargetConfig, _this.ufConsole, _this.x2js);
                }
                else {
                    _this.dsImpl = new uniflash.DSDefaultImpl(_this, _this.$q, _this.$rootScope, _this.$log, _this.ticAlerts, _this.ufSession, _this.ufPrograms, _this.ufPropertiesValue, _this.ufAgentInstallDialog, _this.ufPreferencesSrv, _this.ufContext, _this.ufTargetConfig, _this.ufConsole, _this.x2js);
                }
                // disable auto run on serial connection or PGA devices
                _this.runTargetAfterProgramLoadDisabled = (_this.isSerial() || (_this.partNum.toLowerCase().indexOf('pga9') !== -1));
            });
        }
        DS.prototype.isConfigured = function () {
            return (this.cachedConfigure) ? true : false;
        };
        DS.prototype.getUfPropertiesValue = function () {
            return this.ufPropertiesValue;
        };
        DS.prototype.getCachedConnectedCores = function () {
            return this.cachedConnectedCores;
        };
        DS.prototype.getContext = function () {
            return this.ufContext;
        };
        DS.prototype.getConsole = function () {
            return this.ufConsole;
        };
        DS.prototype.registerProgressEventHandler = function (handler) {
            this.progressEventHandler = handler;
        };
        DS.prototype.registerDSHandler = function (handler) {
            this.dSHandlers = handler;
        };
        DS.prototype.registerTargetSupportHandler = function (handler) {
            this.targetSupportProgressEvents = handler;
        };
        DS.prototype.setupCleanUpTargetSupportProgressEventsHandler = function (agent) {
            if (this.targetSupportProgressEvents) {
                this.cleanUpTargetSupportProgressEvents = this.targetSupportProgressEvents(agent);
            }
        };
        DS.prototype.setupCleanUpDSHandlers = function (agent) {
            if (this.dSHandlers) {
                this.cleanUpDSHandlers = this.dSHandlers(agent);
            }
        };
        DS.prototype.unregisterEventsHandlers = function () {
            if (this.cleanUpTargetSupportProgressEvents) {
                this.cleanUpTargetSupportProgressEvents();
            }
            if (this.cleanUpDSHandlers) {
                this.cleanUpDSHandlers();
            }
            if (this.progressEventHandler) {
                this.progressEventHandler = null;
            }
        };
        DS.prototype.callHandler = function (handler) {
            var handlerArgs = [];
            for (var _i = 1; _i < arguments.length; _i++) {
                handlerArgs[_i - 1] = arguments[_i];
            }
            if (handler) {
                return handler(handlerArgs);
            }
        };
        DS.prototype.addTargetStateListener = function (coreName, listener) {
            if (coreName) {
                this.$log.debug('addTargetStateListener on ' + coreName);
                if (!this.targetStateListeners[coreName]) {
                    this.targetStateListeners[coreName] = [];
                }
                this.targetStateListeners[coreName].push(listener);
            }
        };
        DS.prototype.removeTargetStateListener = function (coreName, listener) {
            if (coreName && this.cachedConnectedCores[coreName]) {
                this.$log.debug('removeTargetStateListener on ' + coreName);
                this.cachedConnectedCores[coreName].targetState.removeListener('changed', listener);
            }
            var listenerArray = this.targetStateListeners[coreName];
            if (listenerArray && listenerArray.length > 0) {
                for (var i = 0; i < listenerArray.length; i++) {
                    if (listenerArray[i] === listener) {
                        listenerArray.splice(i, 1);
                        break;
                    }
                }
            }
        };
        DS.prototype.writeFiles = function (programOBJs) {
            var _this = this;
            // store functions to download program files to disk
            var writeFileFuncs = [];
            // store ds program file format objects to be based to the ds api
            var dsProgramFileObjs = [];
            _.each(programOBJs, function (programObj) {
                writeFileFuncs.push(function () {
                    return _this.dsImpl.writeFileToBeFlashed(programObj.file)
                        .then(function (programFileLocalPath) {
                        if (programObj.isBinary) {
                            dsProgramFileObjs.push({
                                filename: programFileLocalPath,
                                loadAddress: _this.mapLoadAddress(programObj)
                            });
                        }
                        else {
                            dsProgramFileObjs.push({ filename: programFileLocalPath });
                        }
                    });
                });
            });
            return writeFileFuncs.reduce(function (soFar, f) {
                return soFar.then(f);
            }, this.$q.resolve())
                .then(function () {
                return dsProgramFileObjs;
            });
        };
        // cloud Agent Init with modules
        // should init agent + specified modules
        // should be moved to TICloudAgent
        DS.prototype.initWithModules = function (moduleNames) {
            var _this = this;
            var moduleInitPromises = [];
            var agent;
            this.callHandler(this.progressEventHandler, 'Initializing...');
            return TICloudAgent.Init()
                .catch(function (error) {
                if (error instanceof Array) {
                    // cloud agent installation error
                    var deviceXML = _this.ufSession.getDeviceXMLFile();
                    var connectionXML = _this.ufSession.getConnectionXMLFile();
                    var params = {
                        errors: error,
                        deviceID: deviceXML,
                        connectionID: connectionXML
                    };
                    // try to handle the installation issues
                    return TICloudAgent.Install.getInstallWizard(params)
                        .then(function (installWizardObj) {
                        return _this.ufAgentInstallDialog.show(installWizardObj);
                    });
                }
                else {
                    // we can't handle it here, so keep it going up
                    throw error;
                }
            })
                .then(function (newAgent) {
                agent = newAgent;
                _.each(moduleNames, function (moduleName) {
                    moduleInitPromises
                        .push(agent.getSubModule(moduleName)
                        .then(function (module) {
                        agent[moduleName] = module;
                    }));
                });
            })
                .then(function () {
                return _this.$q.all(moduleInitPromises);
            })
                .then(function () {
                return agent;
            });
        };
        DS.prototype.mapLoadAddress = function (programObj) {
            if (programObj.isBinary && !programObj.loadAddress) {
                return 0;
            }
            else if (programObj.loadAddress) {
                return parseInt(programObj.loadAddress, 16);
            }
            else {
                return undefined;
            }
        };
        DS.prototype.getDSCore = function (core) {
            var ret;
            if (uniflash.DSLprfImpl.matches(this.partNum) && !this.isJLink) {
                ret = new uniflash.LPRFCore(core, this);
            }
            else {
                ret = new uniflash.DSCore(core, this);
            }
            return ret;
        };
        DS.prototype.configureLogging = function (enable, filename) {
            var _this = this;
            this.dsLogName = filename;
            return this.dsImpl.configureLogging(enable, filename)
                .then(function (ret) {
                _this.dsLogPath = enable ? ret : null;
                return ret;
            });
        };
        DS.prototype.getLoggingPath = function () {
            return this.dsLogPath;
        };
        DS.prototype.getLoggingName = function () {
            return this.dsLogName;
        };
        DS.prototype.isSerial = function () {
            return this.ufSession.isSerial();
        };
        // get the 'run target after program load' value for the current target
        DS.prototype.getRunTargetAfterProgramLoad = function () {
            if (this.isSerial() || (this.partNum.toLowerCase().indexOf('pga9') !== -1)) {
                return false;
            }
            else if (this.isC2000(this.partNum.toLowerCase())) {
                return this.ufPreferencesSrv.get('runTargetAfterProgramLoadC2000');
            }
            else {
                return this.ufPreferencesSrv.get('runTargetAfterProgramLoad');
            }
        };
        // toggle the current setting of 'run target after program load'
        DS.prototype.toggleRunTargetAfterProgramLoad = function () {
            var id = this.isC2000(this.partNum.toLowerCase()) ? 'runTargetAfterProgramLoadC2000' : 'runTargetAfterProgramLoad';
            return this.ufPreferencesSrv.set(id, !this.ufPreferencesSrv.get(id));
        };
        DS.prototype.isC2000 = function (partnum) {
            return ((partnum.indexOf('tms320f28') !== -1) ||
                (partnum.indexOf('tms320c28') !== -1) ||
                (partnum.indexOf('tms320r28') !== -1) ||
                (partnum.indexOf('f28plc') !== -1) ||
                (partnum.indexOf('f28m3') !== -1));
        };
        DS.$inject = ['$q', '$rootScope', '$log',
            'ticAlerts', 'ufSession', 'ufPrograms',
            'ufPropertiesValue', 'ufAgentInstallDialog',
            'ufPreferencesSrv', 'ufContext', 'ufConsole',
            'ufPropertiesDB', 'ufResets', 'ufTargetConfig', 'x2js'];
        return DS;
    }());
    uniflash.DS = DS;
    angular.module('uniflash').service('ufDS', DS);
})(uniflash || (uniflash = {}));
