var uniflash;
(function (uniflash) {
    var programs;
    (function (programs_1) {
        var Program = (function () {
            function Program(file, provider, isBinary, index, isSelected, loadAddress) {
                if (isSelected === void 0) { isSelected = true; }
                this.file = file;
                this.provider = provider;
                this.isBinary = isBinary;
                this.index = index;
                this.isSelected = isSelected;
                this.loadAddress = loadAddress;
            }
            Program.prototype.toJSON = function () {
                return {
                    file: this.file.toJSON(),
                    isBinary: this.isBinary,
                    index: this.index,
                    isSelected: this.isSelected,
                    provider: this.provider.type,
                    loadAddress: this.loadAddress
                };
            };
            return Program;
        }());
        programs_1.Program = Program;
        'use strict';
        angular.module('uniflash').service('ufPrograms', programs);
        programs.$inject = ['ufSession', 'ufContext', 'ufIsBinary', 'ticFileFactory', 'ufProgramProviders'];
        function programs(ufSession, ufContext, ufIsBinary, ticFileFactory, ufProgramProviders) {
            var cores = {};
            function createProgramFromJSON(program) {
                return new Program(ticFileFactory.createFromJSON(program.file), ufProgramProviders[program.provider], program.isBinary, program.index, program.isSelected, program.loadAddress);
            }
            ufSession.registerSessionDataProvider('programs', {
                onSessionLoad: function (newData) {
                    cores = {}; // reset data
                    // init cores
                    _.each(ufSession.queryConfig().cores, function (coreInfo) {
                        cores[coreInfo.name] = {
                            name: coreInfo.name,
                            programs: []
                        };
                    });
                    if (newData) {
                        // deserialize
                        _.each(newData, function (core) {
                            if (cores[core.name]) {
                                cores[core.name].programs = _.map(core.programs, function (program) {
                                    return createProgramFromJSON(program);
                                });
                            }
                            else {
                                console.log("Warning! no core found while loading session data, core id = " + core.name);
                            }
                        });
                    }
                },
                getSessionData: function () {
                    var toJSON = [];
                    _.each(cores, function (core) {
                        var programs = _.map(core.programs, function (program) {
                            return program.toJSON();
                        });
                        toJSON.push({
                            name: core.name,
                            programs: programs
                        });
                    });
                    return toJSON;
                }
            });
            function getCoreData() {
                return cores[ufContext.getCurrentCore().name];
            }
            function getAllGUICoresData() {
                return _.map(ufSession.queryConfig().cores, function (coreInfo) {
                    return cores[coreInfo.name];
                });
            }
            function getPrograms() {
                return getCoreData().programs;
            }
            function getProgramsOnCore(coreName) {
                if (coreName && cores[coreName]) {
                    return cores[coreName].programs;
                }
                else {
                    return undefined;
                }
            }
            function getProgramsOnAllCores() {
                var programs = [];
                _.each(ufSession.queryConfig().cores, function (coreInfo) {
                    programs.concat(cores[coreInfo.name].programs);
                });
                return programs;
            }
            // We need to track the position of the program in the list because it is sortable and supports duplicates
            // The sorting messes up the $index property of ng-repeat so when we try to remove using it we remove the
            // wrong item. Therefore removing via $index is not an option. We could remove by reference ( search and find index)
            // but that would only find the first instance. Thus we need to have each program uniquely identify itself via the index
            // and keep the index updated.
            function addProgram(file, programProvider, order) {
                var programs = getPrograms();
                var index = programs.length;
                if (order !== undefined) {
                    programs.push(new Program(file, programProvider, true, index, true, order.toString()));
                }
                else {
                    programs.push(new Program(file, programProvider, ufIsBinary(file), index));
                }
            }
            function removeProgram(program) {
                var programs = getPrograms();
                programs.splice(program.index, 1);
                _.each(programs, function (program, index) {
                    program.index = index;
                });
            }
            return {
                getPrograms: getPrograms,
                getAllGUICoresData: getAllGUICoresData,
                getProgramsOnCore: getProgramsOnCore,
                getProgramsOnAllCores: getProgramsOnAllCores,
                addProgram: addProgram,
                removeProgram: removeProgram
            };
        }
    })(programs = uniflash.programs || (uniflash.programs = {}));
})(uniflash || (uniflash = {}));
