(function () {
    'use strict';
    angular.module('uniflash').directive('ufProgramsList', programsList);
    function programsList() {
        var directive = {
            templateUrl: 'programs/programs_list.html',
            restrict: 'E',
            controller: ProgramsListController,
            controllerAs: 'vm',
            scope: {}
        };
        return directive;
    }
    var headings = [
        {
            name: 'File Name',
            sortProperty: 'fd.name',
            colSize: 4
        },
        {
            name: 'Size',
            sortProperty: 'fd.size',
            colSize: 1
        },
        {
            name: 'Binary',
            colSize: 1
        },
        {
            name: 'Load Address',
            colSize: 2
        },
        {
            name: 'Actions',
            colSize: 3
        },
        {
            name: '',
            colSize: 1
        }
    ];
    ProgramsListController.$inject = ['ufPrograms', 'ufResets', 'ufProgramProviders', 'ufDsProgressDialog', 'ufContext', 'ufMainView', 'ticAnalyticsSrv', 'ufSession', 'ufConsole', 'ufDS'];
    function ProgramsListController(ufPrograms, ufResets, ufProgramProviders, ufDsProgressDialog, ufContext, ufMainView, ticAnalyticsSrv, ufSession, ufConsole, ufDS) {
        var vm = this;
        var coreName = ufContext.getCurrentCore().name;
        vm.ufDS = ufDS;
        vm.resets = ufResets.getReset();
        vm.headings = headings;
        vm.programs = ufPrograms.getPrograms();
        vm.programProviders = ufProgramProviders;
        vm.connectionProperties = ufSession.queryConfig().connectionProperties;
        vm.deviceProperties = ufSession.queryConfig().deviceProperties;
        vm.numDefaultImageSelection = 1;
        vm.imageSelectionNames = [];
        // do not show reset actions for serial connection (update rules as necessary)
        vm.showResetActions = (ufContext.$stateParams.connectionXMLFile !== "Serial_Connection");
        vm.queryResets = function () {
            var dsCore = ufDsProgressDialog.getDSCore(coreName);
            return dsCore.run('getResets')
                .then(function (ret) {
                vm.resets.availableResetOptions = ret;
                if (vm.resets.availableResetOptions.length > 0) {
                    vm.resets.selectedResetOption = vm.resets.availableResetOptions[0];
                }
            });
        };
        vm.performReset = function () {
            ufConsole.addMessage('INFO', 'Executing Reset: ' + vm.resets.selectedResetOption);
            var dsCore = ufDsProgressDialog.getDSCore(coreName);
            return dsCore.run('performReset', vm.resets.selectedResetOption);
        };
        vm.fillDefaultImageSelection = function () {
            if (vm.connectionProperties.ufSupportMultipleImageSelect && vm.connectionProperties.ufSupportMultipleImageSelect.Value === 'true') {
                if (vm.deviceProperties.ufNumImageSelection) {
                    vm.numDefaultImageSelection = parseInt(vm.deviceProperties.ufNumImageSelection.Value);
                    for (var i = 0; i < vm.numDefaultImageSelection; i++) {
                        vm.imageSelectionNames[i] = vm.deviceProperties['ufImageType' + i.toString()].Value;
                    }
                }
            }
        };
        this.fillDefaultImageSelection();
        // program list ordering
        vm.reverse = false;
        vm.predicate = "";
        vm.order = function (predicate) {
            vm.predicate = predicate;
        };
        vm.goToUtilitiesAndSettings = function () {
            ufMainView.go(uniflash.RegisteredViews.UtilitiesAndSettings, coreName);
        };
        vm.hasBinary = function () {
            var rtnVal = false;
            _.each(vm.programs, function (program) {
                if (program.isBinary) {
                    rtnVal = true;
                    return;
                }
            });
            return rtnVal;
        };
        vm.performDSAction = function (action, param) {
            var dsCore = ufDsProgressDialog.getDSCore(coreName);
            ticAnalyticsSrv.record("PerformSingle", {
                "action": action,
                "isBinary": param[0].isBinary
            });
            return dsCore.run(action, param);
        };
        vm.selectClicked = function (programProvider, order) {
            programProvider.selectProgramFile(vm.getFileExtensions(order)).then(function (selections) {
                _.each(selections, function (selection) {
                    if (order !== undefined) {
                        // remove the entry first before adding
                        var program = vm.findImageByIndex(order);
                        if (program.file) {
                            vm.removeClicked(vm.findImageByIndex(order));
                        }
                    }
                    ufPrograms.addProgram(selection, programProvider, order);
                });
            }).catch(programFileSelectError);
        };
        vm.browseClicked = function (program) {
            program.provider.selectProgramFile(vm.getFileExtensions(0)).then(function (selections) {
                // just change the file descriptor
                // if multiple selections just use the first one
                program.file = selections[0];
            }).catch(programFileSelectError);
        };
        vm.getFileExtensions = function (index) {
            if (index > 1) {
                // look up file filter for when we have multiple files defined
                var fileExtensionObj = vm.deviceProperties["supportedFileExtensions" + (index - 1).toString()];
                if (fileExtensionObj) {
                    return fileExtensionObj.Value;
                }
            }
            return vm.deviceProperties.supportedFileExtensions ?
                vm.deviceProperties.supportedFileExtensions.Value : '.out,.bin,.hex,.txt';
        };
        vm.removeClicked = function (program) {
            ufPrograms.removeProgram(program);
        };
        vm.removeAll = function () {
            while (vm.programs.length > 0) {
                ufPrograms.removeProgram(vm.programs[0]);
            }
        };
        vm.loadSelectedClicked = performAllSelected.bind(this, 'program');
        vm.verifySelectedClicked = performAllSelected.bind(this, 'verify');
        // Three state sorting
        // 1) no predicate -> un sorted
        // 2) predicate , sort asending
        // 3) predicate , sort descending
        // 1 -> 2 
        // 2 -> 3 | 2 ( where the predicate changes)
        // 3 -> 1 | 3 ( where the predicate changes)
        //
        // Thus if we keep clicking on the same column it goes 
        //  sort ascending, sort descending, unsorted
        //
        vm.order = function (predicate) {
            if (vm.predicate === predicate) {
                if (vm.reverse) {
                    // no sort
                    vm.predicate = undefined;
                    vm.reverse = undefined;
                }
                else {
                    vm.reverse = true;
                }
            }
            else {
                vm.predicate = predicate;
                vm.reverse = false;
            }
        };
        vm.selectedActionsDisabled = function () {
            return vm.numProgramsSelected() < 2 || vm.allSelectedActionInProgress;
        };
        vm.numProgramsSelected = function () {
            return _.reduce(vm.programs, function (totalSelected, program) {
                return program.isSelected ? ++totalSelected : totalSelected;
            }, 0);
        };
        function performAllSelected(action) {
            vm.allSelectedActionInProgress = true;
            var curPrograms = vm.sortedPrograms;
            if (!curPrograms) {
                curPrograms = vm.programs;
            }
            var programsToLoad = _.filter(curPrograms, { isSelected: true });
            ticAnalyticsSrv.record("PerformAll", {
                "action": action,
                "numPrograms": programsToLoad.length,
                "hasBinary": vm.hasBinary()
            });
            var dsCore = ufDsProgressDialog.getDSCore(coreName);
            return dsCore.run(action, programsToLoad)
                .finally(function () {
                vm.allSelectedActionInProgress = false;
            });
        }
        vm.programRowClass = function (program) {
            return {
                disabled: !program.file.isReady,
                highlight_hover_light2: vm.programs.length > 1
            };
        };
        vm.checkHex = function (program) {
            program.loadAddress = program.loadAddress.replace(/[^A-Fa-f0-9xX]/g, '');
        };
        vm.findImageByIndex = function (index) {
            var program = _.find(vm.programs, function (program) {
                return (program.loadAddress === index.toString());
            });
            if (program) {
                return program;
            }
            else {
                return { isSelected: false };
            }
        };
        vm.verifySupported = function () {
            if (vm.connectionProperties.ufSupportVerify && vm.connectionProperties.ufSupportVerify.Value === 'false') {
                return false;
            }
            return true;
        };
    }
    function programFileSelectError(e) {
        console.log(e);
    }
}());
