Source: directives/msi/msi.js

/**
 * @ngdoc directives
 * @name Msi
 * @module s4c.directives.msi.Msi
 *
 * @description
 * `Msi` Controller do módulo de msi 
 * 
 * @example <s4c-msi></s4c-msi>
 */
(function () {
    'use strict';

    msiController.$inject = [
        '$scope',
        '$http',
        'API_ENDPOINT',
        '$window',
        '$filter',
        '$anchorScroll',
        'ngTableParams',
        'MsiService',
        'MsiFilter',
        'IncidentesService',
        'CommService',
        'MainState',
        'DetalhamentoManager',
        'IncidentesManager',
        'MapaService',
        'CamadasService',
        '$mdDialog',
        '$timeout',
        'Preset',
        '$q',
        '$attrs'
    ];

    function msiController(
        $scope,
        $http,
        API_ENDPOINT,
        $window,
        $filter,
        $anchorScroll,
        ngTableParams,
        MsiService,
        MsiFilter,
        IncidentesService,
        CommService,
        MainState,
        DetalhamentoManager,
        IncidentesManager,
        MapaService,
        CamadasService,
        $mdDialog,
        $timeout,
        Preset,
        $q, $attrs) {

        $scope.res = $scope.$root.res;
        $scope.incidentToStore;

        /**
         * @method registerFilterListeners
         */
        function registerFilterListeners() {
            MsiFilter.getInstance($attrs.id).on('filterChanged', loadIncidentes);
            MsiFilter.getInstance($attrs.id).on('moduloMsiFechado', setModuloMsiFechado);
            MsiFilter.getInstance($attrs.id).on('filterChangedMenu', function (array) {
                var incidentes = null;
                var menu = null;
                var incidentesList_ = null;
                var incidentesAntigos = [];

                if (array != null) {
                    incidentes = array[0];
                    menu = array[1];
                    if (incidentes != null && incidentes.length > 0) {
                        incidentesList_ = $scope.incidentes.concat(incidentes);
                    } else {
                        incidentesList_ = $scope.incidentes;
                    }
                }

                if (incidentesList_ != null && incidentesList_.length > 0) {
                    _.each(menu.parentNode.subMenus, function (subMenu) {
                        if (subMenu.ativo) {
                            _.each(incidentesList_, function (incidenteLocal) {
                                if (incidenteLocal.CategoriaIncidenteId == subMenu.categoriaIncidenteId && incidenteLocal.status == subMenu.parentNode.texto) {
                                    incidentesAntigos.push(incidenteLocal);
                                }
                            });
                        }
                    });
                }

                if (incidentesAntigos.length == 0 || incidentesAntigos == null) {
                    $scope.incidentes = [];
                } else {
                    $scope.incidentes = incidentesAntigos;
                }

                var novosIncidentes = incidentes;
                var incidentesList = null;
                if (novosIncidentes != null) {
                    incidentesList = $scope.incidentes.concat(novosIncidentes);
                }

                if (incidentesList != null) {
                    $scope.incidentes = _filterAfterQuery(novosIncidentes);
                    var parsedIncidentes = $scope.incidentes.map(function (incidente) {
                        return parseToGrid(incidente);
                    });

                    $scope.incidentesGrid.data = parsedIncidentes;
                }
                $scope.nothingFound = (!$scope.incidentes.length);

            });
        }

        registerFilterListeners();

        /**
         * @method _filterAfterQuery
         * @param {*} incidentes 
         */
        function _filterAfterQuery(incidentes) {
            var newIncidentes = _.chain(incidentes).map(parseIncidente).value();

            newIncidentes = _filterAberto24h(incidentes);
            newIncidentes.forEach(function (obj, index) {
                if (obj.extras != null && obj.extras.informacoes != null) {
                    obj.extras.informacoes.filter(function (item, i) {
                        if (item.label === 'Prioridade') {
                            delete obj.extras.informacoes[i];
                        }
                    });
                }
            });

            return newIncidentes;
        }

        // 1. Aberto 2. Fechado 3. Aberto 24h
        /**
         * @method _filterAberto24h
         * @param {*} incidentes 
         */
        function _filterAberto24h(incidentes) {
            var filterData = _getFilterData();
            var statuses = _filtrarAtivos(filterData.statuses, 'id');
            var timeWindow = _setTimeWindow(filterData.timeWindow, statuses);

            var newIncidentes = incidentes.filter(function (incidente) {
                if (!statuses.length) return incidente;

                if (incidente.status === 'ABERTO' && statuses.indexOf(1) === -1) {
                    if (incidente.inicio.isBefore(moment(timeWindow.start))) {
                        return incidente;
                    }
                } else {
                    return incidente;
                }
            });

            return newIncidentes;
        }

        var filterInstance = MsiFilter.getInstance($attrs.id);

        $scope.incidentesGrid = [];
        $scope.incidentes = [];
        $scope.moduleFilter = {
            nome: '',
            agencia: ''
        };
        var dateFormat = 'DD/MM/YYYY - HH:mm:ss';
        /**
         * @instance fields
         * @memberof Msi
         */
        $scope.fields = [
            {
                active: true,
                pinnedLeft: true,
                enableFiltering: false,
                name: '',
                field: 'statusIcon',
                width: 40,
                headerCellClass: 'tableHeader',
                enableColumnMenu: false,
                cellClass: 'tableRow',
                headerCellTemplate: '<md-icon md-svg-icon="settings:engine" class="settings" ng-click="grid.appScope.toggleFieldSelection()"></md-icon>',
                cellTemplate: '<img ng-src="{{grid.appScope.setIconUrl(row)}}" ng-click="grid.appScope.openDetalhamentoFromRow(row)" width="14" height="14" style="margin-left: 7px; margin-top: 7px;"/>'
            }, {
                active: true,
                name: $scope.res('DETALHAMENTO_DATAHORA'),
                field: 'inicioFormated',
                sort: { direction: 'desc', priority: 0 },
                enableSorting: true,
                sortingAlgorithm: function (firstDateString, secondDateString) {
                    if (!firstDateString && !secondDateString) {
                        return 0;
                    }
                    if (!firstDateString) {
                        return 1;
                    }
                    if (!secondDateString) {
                        return -1;
                    }
                    var firstDate = moment(firstDateString, dateFormat);
                    if (!firstDate.isValid()) {
                        throw new Error('Invalid date: ', firstDateString);
                    }
                    var secondDate = moment(secondDateString, dateFormat);
                    if (!firstDate.isValid()) {
                        throw new Error('Invalid date: ', secondDateString);
                    }
                    if (firstDate.isSame(secondDate)) {
                        return 0;
                    } else {
                        return firstDate.isBefore(secondDate) ? -1 : 1;
                    }
                },
                width: 170,
                headerCellClass: 'tableHeader',
                enableColumnMenu: false,
                cellClass: 'tableRow'
            }, {
                active: true,
                name: $scope.res('MSI_NOME'),
                field: 'nome',
                enableColumnMenu: false,
                width: 200,
                headerCellClass: 'tableHeader',
                cellClass: 'tableRow'
            }, {
                active: true,
                name: $scope.res('DETALHAMENTO_STATUS'),
                field: 'status',
                width: 110,
                enableColumnMenu: false,
                headerCellClass: 'tableHeader',
                cellClass: 'tableRow'
            }, {
                active: true,
                name: $scope.res('COMUM_CATEGORIA'),
                field: 'CategoriaNome',
                width: 150,
                enableColumnMenu: false,
                headerCellClass: 'tableHeader',
                cellClass: 'tableRow'
            }, {
                active: true,
                name: $scope.res('COMUM_FILTRO'),
                field: 'filtro',
                width: 150,
                enableColumnMenu: false,
                headerCellClass: 'tableHeader',
                cellClass: 'tableRow'
            }
        ];

        $scope.qtdMSIAbertos = 0;
        $scope.qtdMSIFechados = 0;
        /**
         * @method countByStatus
         * @param {*} query 
         */
        function countByStatus(query) {

            if (query != undefined || query != null || query != "") {
                IncidentesService.getCountStatus(query).then(function (data) {
                    $scope.qtdMSIAbertos = 0;
                    $scope.qtdMSIFechados = 0;
                    data.forEach(function (e) {
                        if (e.key == 'ABERTO') {
                            $scope.qtdMSIAbertos = e.value;
                        } else if (e.key == 'FECHADO') {
                            $scope.qtdMSIFechados = e.value;
                        }
                    });
                });
            }
        }

        /**
         * @method counterByStatusIncidentes
         * @param {*} incidentes 
         */
        function counterByStatusIncidentes(incidentes) {
            $scope.qtdMSIAbertos = 0;
            $scope.qtdMSIFechados = 0;

            _.each(incidentes, function (incidente) {
                if (incidente.status == "ABERTO") {
                    $scope.qtdMSIAbertos++;
                }
                else if (incidente.status == "FECHADO") {
                    $scope.qtdMSIFechados++;
                }
            });
        }

        // Main Load of Incidentes
        $scope.pageNumber = 0;
        $scope.loadIncidente = true;
        /**
         * @method loadIncidentes
         * @param {*} origem 
         * @param {*} incidenteRemovido 
         */
        function loadIncidentes(origem, incidenteRemovido) {

            if (origem && origem != 'clearIncidentes') {

                $scope.pageNumber = 0;
                $scope.hasResults = true;
                $scope.incidentes = [];
                maxVerticalScroll = 0;

            } else if (origem == 'clearIncidentes') {

                if (containsIncidente(incidenteRemovido)) {
                    $scope.incidentes = _.filter($scope.incidentes, function (inc) {
                        return inc.id != incidenteRemovido.id;
                    });
                    loadTable($scope.incidentes);
                    counterByStatusIncidentes($scope.incidentes);
                    return;
                } else {
                    verificaMenuCarregado($scope.incidentes);
                    return;
                }
            }

            if (!$scope.loadIncidente) {
                return;
            }

            if (origem == "loadTela" && filterInstance.lastTableQueryFilter != null) {
                query = filterInstance.lastTableQueryFilter;
                $scope.primeiraVezCarregaLayer = true;

                var interval = setTimeout(function () {
                    clearInterval(interval);
                    var msiFilter = MainState.getDirective('msiFilter');
                    if (msiFilter) {
                        msiFilter.setFilter(query.where);
                    }
                }, 1000);
            }

            var filterData = _getFilterData();
            var query = _setQuery(filterData);
            $scope.loadIncidente = false;

            query.pageNumber = $scope.pageNumber;
            $scope.moduloMsiFechado = false;

            $scope.presetId = Preset.obter().id;
            query.parameters = {};
            if (MsiFilter.getInstance($attrs.id) != null && MsiFilter.getInstance($attrs.id).modulo != null) {
                query.parameters.moduloId = MsiFilter.getInstance($attrs.id).modulo.id;
            } else {
                query.parameters.moduloId = -1;
            }
            query.parameters.statuses = filterData.statuses;
            query.parameters.presetId = $scope.presetId;

            if (query.parameters.statuses) {
                query.parameters.date = filterData.timeWindow;
            }
            filterInstance.lastTableQueryFilter = query;

            setTimeout(function () {
                var msiFilter = MainState.getDirective('msiFilter');
                if (msiFilter) {
                    msiFilter.setFilter(query.where);
                }
            }, 1000);

            IncidentesService.findSimpleByFilter(query)
                .then(function (incidentes) {

                    $scope.loadIncidente = true;
                    if (!incidentes || incidentes.length == 0) {
                        $scope.hasResults = false;
                        loadTable($scope.incidentes);
                        counterByStatusIncidentes($scope.incidentes);
                        return;
                    }

                    $scope.incidentes = _filtrarIncidentes(incidentes).concat($scope.incidentes);
                    loadTable($scope.incidentes);

                    if ($scope.pageNumber == 0) {
                        countByStatus(query);
                    }
                });
        }

        /**
         * @method containsIncidente
         * @param {*} inc 
         */
        function containsIncidente(inc) {

            for (var index in $scope.incidentes) {
                if ($scope.incidentes[index].id == inc.id) {
                    return true;
                }
            }

            return false;
        }

        /**
         * @method incidentes
         */
        CommService.on('incidentes', function (incidente) {
            adicionaNovoIncidenteManual(incidente);
        });

        /**
         * @method removeIncidentes
         */
        CommService.on('removeIncidentes', function (incidente) {
            for (var index in $scope.incidentes) {
                var incidenteLista = $scope.incidentes[index];
                if (incidenteLista.chave_estrangeira === incidente.chave_estrangeira) {
                    $scope.$apply(function () {
                        $scope.incidentes.splice(index, 1);
                        DetalhamentoManager.fechar();
                        loadTable($scope.incidentes);
                        counterByStatusIncidentes($scope.incidentes);
                        return;
                    });
                }
            }

        });

        /**
         * @method updateIncident
         */
        CommService.on('updateIncident', function (incidente) {

            if (incidente.status != 'FECHADO') {
                return;
            }

            var incidente_ = _.find($scope.incidentes, function (incidente_param) { return incidente_param.id === incidente.id; });
            var status = _.find(statuses, function (status) { status == 'FECHADO' });

            if (incidente_) {

                if (status) {
                    atualizaIncidente(incidente);
                } else if (!status) {
                    $scope.$apply(function () {
                        $scope.incidentes.splice($scope.incidentes.indexOf(incidente_), 1);
                        loadTable($scope.incidentes);
                        counterByStatusIncidentes($scope.incidentes);
                    });
                }
            }
        });


        /**
         * @method addIncidente
         * @param {*} incidente 
         */
        function addIncidente(incidente) {

            for (var index in $scope.incidentes) {
                if ($scope.incidentes[index].id === incidente.id) {
                    return;
                }
            }

            CamadasService.reloadIncidentes(true);

            var inc = DetalhamentoManager.abrirIncidente(incidente.id, {
                lat: incidente.geometry.coordinates[1],
                lng: incidente.geometry.coordinates[0]
            });

            if (!incidente.CategoriaIncidente) {
                var interval = setTimeout(function () {
                    incidente.CategoriaNome = inc.CategoriaIncidente.nome;
                }, 200);
            }

            var incidentes = [];
            incidentes.push(incidente);
            incidentes = _filtrarIncidentes(incidentes);
            $scope.incidentes.push(incidentes[0]);
            loadTable($scope.incidentes);
            $scope.loadIncidente = true;
            counterByStatus($scope.incidentes);
        }

        /**
         * @method showInMap
         * @param {*} incidente 
         */
        function showInMap(incidente) {

            incidente.properties = { urlIcone: '/data-s4c/Incidentes/CADS/s4c_ic_incident_vermelho_color2.png' };

            var hasInc = false;
            for (var index in $scope.incidentes) {
                if ($scope.incidentes[index].id === incidente.id) {
                    hasInc = true;
                }
            }

            if (!hasInc) {
                $scope.incidentes.push(incidente);
            }
            CamadasService.ativarMenuIncidente();
            $scope.voarIncidente(incidente);
        }

        /**
         * @method adicionaNovoIncidenteManual
         * @param {*} incidente 
         */
        function adicionaNovoIncidenteManual(incidente) {

            if (incidente != null && incidente != undefined) {
                $scope.$apply(function () {
                    $scope.incidentToStore = parseIncidente(incidente);
                    var incidente_ = _.find($scope.incidentes, function (incidente_param) { return incidente_param.id === incidente.id; });
                    if ($scope.incidentToStore && incidente_ == null) {
                        $scope.incidentes.push(angular.copy($scope.incidentToStore));
                        $scope.incidentToStore = undefined;
                    }

                    loadTable($scope.incidentes);
                    counterByStatusIncidentes($scope.incidentes);
                });
            }
        }

        /**
         * @method atualizaIncidente
         * @param {*} incidente 
         */
        function atualizaIncidente(incidente) {

            var incidente_ = _.find($scope.incidentes, function (incidente_param) { return incidente_param.id === incidente.id; });
            if (incidente_ != null) {
                incidente_.status = incidente.status;
                incidente_.urlIcone = incidente.urlIcone;
                loadTable($scope.incidentes);
            }
        }

        $scope.lastRow = { id: -1 };
        /**
         * @method loadTable
         * @param {*} incidentes 
         */
        function loadTable(incidentes) {
            var parsedIncidentes = incidentes.map(function (incidente) {
                return parseToGrid(incidente);
            });

            $scope.incidentesGrid.data = parsedIncidentes;

            /*
             * When Row of Table is clicked, rowSelectionChanged is invoked
            */
            if ($scope.gridApi) {
                $scope.gridApi.selection.on.rowSelectionChanged(null, function (row) {
                    if ($scope.lastRow.id == row.entity.id) {
                        return;
                    }

                    $scope.lastRow = row;
                    $scope.voarIncidente(row.entity, true);
                    verificaMenuCarregado(incidentes);
                });

                resizeTable();
            }

            verificaMenuCarregado(incidentes);
        }

        // Watch the Module Size
        /**
         * @method $watch
         * 
         */
        $scope.$watch(
            function () {
                if (angular.element('#modulo-msi')[0] != null) {
                    return angular.element('#modulo-msi')[0].offsetHeight
                }
            },
            function (value) {
                resizeTable();
            }
        );

        /**
         * @method setIconUrl
         */
        $scope.setIconUrl = function (row) {
            var incidente = row.entity;
            if (incidente.status == "ABERTO") {
                return "/assets/images/IncidenteLegenda/s4c_ic_incident_open_fill_subtitle.svg";
            } else if (incidente.status == "FECHADO") {
                return "/assets/images/IncidenteLegenda/s4c_ic_incident_closed_fill_subtitle.svg";
            }
        };

        /**
         * @method openDetalhamentoFromRow
         */
        $scope.openDetalhamentoFromRow = function (row) {
            var incidente = row.entity;
            $scope.abrirDetalhamento(incidente);
        };

        /**
         * @method resizeTable
         */
        function resizeTable() {
            if ($scope.gridApi) {

                if (angular.element('#modulo-msi')[0] && angular.element('.msi-tabs')[0]) {
                    var gridSize = $scope.gridApi.grid.gridHeight;
                    var moduleHeight = angular.element('#modulo-msi')[0].clientHeight;
                    var tabsHeight = angular.element('.msi-tabs')[0].clientHeight;

                    var gridHeight = moduleHeight - tabsHeight - 67;
                    $scope.uiGridHeight = { height: gridHeight + 'px' };
                }
            }
        }

        /**
         * @method getCategorias
         */
        MsiService.getCategorias()
            .then(function (agencias) {
                var agenciasList = $filter('orderBy')(agencias, '-nome');

                $scope.agencias = agenciasList;
                $scope.agencias.unshift({ id: '', nome: $scope.res('COMUM_TODOS') });
            });


            /**
             * @method filterTab
             */
        $scope.filterTab = function (agencia) {
            $scope.moduleFilter.agencia = (agencia.nome === $scope.res('COMUM_TODOS')) ? '' : agencia.id;
            searchByTab();
        };

        /**
         * @method searchByTab
         */
        function searchByTab() {

            if (!MainState.getDirective('msiFilter')) {
                return;
            }
            MainState.getDirective('msiFilter').initFilter().then(function (data) {
                loadIncidentes('origem');
                $scope.moduleFilter.agencia = '';
            });

        }

        $scope.searchText;
        $scope.searchTable = function (filter) {

            $scope.searchText = filter.nome;
            loadIncidentes('origem');
        };

        $scope.incidentesGrid = {
            enableRowSelection: true,
            enableRowHeaderSelection: false,
            multiSelect: false,
            flatEntityAccess: true,
            fastWatch: true,
            noUnselect: true,
            columnDefs: $scope.fields
        };

        $scope.incidentesGrid.onRegisterApi = function (gridApi) {
            $scope.gridApi = gridApi;
        };

        /**
         * @method parseToGrid
         * @param {*} incidente 
         */
        function parseToGrid(incidente) {
            incidente.statusIcon = (incidente.status === 'ABERTO') ? 'opened' : 'closed';

            if (incidente.inicio) {
                incidente.inicioFormated = moment(incidente.inicio).format('DD/MM/YYYY - HH:mm:ss');
            }

            if (incidente.CategoriaIncidente != null) {
                incidente.CategoriaNome = incidente.CategoriaIncidente.nome;
            }

            return incidente;
        }

        /**
         * @method verificaMenuCarregado
         * @param {*} incidentes 
         */
        function verificaMenuCarregado(incidentes) {
            if (!CamadasService.isLoaded) {
                CamadasService.isLoaded = true;
                var interval = setTimeout(function () {
                    clearInterval(interval);
                    verificaMenuCarregado(incidentes);
                }, 10);
            } else {
                _updateCamadasService();
            }
        }

        $scope.camadasCarregadas = false;
        /**
         * @method _updateCamadasService
         */
        function _updateCamadasService() {

            MapaService.naoPiscar();

            if (!$scope.camadasCarregadas) {
                //Uso um timeout para dar tempo do menu camada carregar
                var interval = setTimeout(function () {
                    clearInterval(interval);
                    CamadasService.ativarMenuIncidente();
                    $scope.camadasCarregadas = true;
                }, 2000);
            } else {
                clearInterval(interval);
                CamadasService.ativarMenuIncidente();
            }
        }

        $scope.camadasList = [];
        /**
         * @method carregarLayerIncidentes
         * @param {*} node 
         */
        function carregarLayerIncidentes(node) {

            var collections = [];
            var featureMap = {};

            _.each($scope.incidentes, function (incidente) {

                var featureCollection = createFeatureCollection(incidente, featureMap);

                collections = updateCollections(collections, featureCollection);
            });

            removerCamadas().then(function () {
                _.each(collections, function (featureCollection) {
                    CamadasService._adicionarPontos(featureCollection, node).then(function (_camada) {

                        for (var index in _camada) {
                            if (_camada[index].aggregate) {
                                $scope.camadasList.push(_camada[index]);
                            }
                        }
                    });
                });

                CamadasService.isLoaded = true;
            });
        }

        /**
         * @method createFeatureCollection
         * @param {*} incidente 
         * @param {*} featureMap 
         */
        function createFeatureCollection(incidente, featureMap) {

            var featureCollection;

            if (featureMap[incidente.CategoriaIncidenteId] == null || featureMap[incidente.CategoriaIncidenteId] == undefined) {
                featureCollection = { features: [], type: "FeatureCollection", CategoriaIncidenteId: incidente.CategoriaIncidenteId };
                featureMap[incidente.CategoriaIncidenteId] = featureCollection;

            } else {
                featureCollection = featureMap[incidente.CategoriaIncidenteId];
            }

            var feature = {
                geometry: incidente.geometry,
                type: "Feature",
                properties: {
                    id: incidente.id,
                    nome: incidente.nome,
                    status: incidente.status,
                    CategoriaIncidente: incidente.CategoriaIncidente,
                    urlIcone: incidente.urlIcone,
                    urlIconeFechado: incidente.urlIconeFechado,
                    chaveEstrangeira: incidente.chaveEstrangeira,
                    qtdComentarios: incidente.qtdComentarios
                }
            };
            featureCollection.features.push(feature);
            var urlClusterIcone;

            if ($scope.incidentes[0].CategoriaIncidente != null && $scope.incidentes[0].CategoriaIncidente.urlIcone != null && "ABERTO" == $scope.incidentes[0].status) {
                urlClusterIcone = $scope.incidentes[0].CategoriaIncidente.urlIcone;
            } else if ($scope.incidentes[0].CategoriaIncidente != null && $scope.incidentes[0].CategoriaIncidente.urlIconeFechado != null && "FECHADO" == $scope.incidentes[0].status) {
                urlClusterIcone = $scope.incidentes[0].CategoriaIncidente.urlIconeFechado;
            }

            var properties = { cluster: true, tipo: "incidente", urlClusterIcone: urlClusterIcone };
            featureCollection.properties = properties;

            return featureCollection;
        }

        /**
         * @method removerCamadas
         */
        function removerCamadas() {

            var p = $q.defer();
            removerCamadasRecursivo(p, 0);
            return p.promise;
        }

        /**
         * @method removerCamadasRecursivo
         * @param {*} p 
         * @param {*} index 
         */
        function removerCamadasRecursivo(p, index) {

            if (index == $scope.camadasList.length) {
                p.resolve('');
                $scope.camadasList = [];
                return;
            }

            var camada = $scope.camadasList[index];

            if (camada && camada.aggregate) {
                MapaService.removerCamada(camada.aggregate).then(function () {
                    index += 1;
                    removerCamadasRecursivo(p, index);
                });
            } else {
                index += 1;
                removerCamadasRecursivo(p, index);
            }
        }

        /**
         * @method updateCollections
         * @param {*} collections 
         * @param {*} featureCollection 
         */
        function updateCollections(collections, featureCollection) {

            var index = -1;

            for (var i = 0; i < collections.length; i++) {
                if (collections[i].CategoriaIncidenteId == featureCollection.CategoriaIncidenteId) {
                    index = i;
                    break;
                }
            }

            if (index > -1) {
                collections[index] = featureCollection;
            }
            else {
                collections.push(featureCollection);
            }

            return collections;
        }

        $scope.fieldSelection = false;
        $scope.toggleFieldSelection = function () {
            $scope.incidentesGrid.columnDefs = $scope.fields.filter(function (column) {
                return column.active === true;
            });
            $scope.fieldSelection = !$scope.fieldSelection;
        };

        /**
         * @method parseIncidente
         * @param {*} incidente 
         */
        function parseIncidente(incidente) {

            if (incidente.inicio) {
                incidente.inicio = moment(moment(incidente.inicio).toDate());
            }

            if (incidente.fim) {
                incidente.fim = moment(moment(incidente.fim).toDate());
            }

            if (incidente.fim &&
                incidente.status === 'FECHADO' &&
                incidente.inicio) {

                if (moment().dayOfYear() - incidente.fim.dayOfYear() >= 1) {
                    incidente.icon = '/data-s4c/teste/ic_incidentes_grey_26px.svg';
                }
            }

            if (incidente.status && incidente.status === 'ABERTO') {
                incidente.icon = '/data-s4c/teste/ic_incidentes_red_26px.svg';
            }

            return incidente;
        }

        /**
         * @method _filtrarIncidentes
         * @param {*} incidentes 
         */
        function _filtrarIncidentes(incidentes) {
            return _.chain(incidentes)
                .map(parseIncidente)
                .sortBy(function (incidente) {
                    if (incidente.status === 'ABERTO') {
                        return 0;
                    }

                    if (incidente.fim && moment().dayOfYear() - incidente.fim.dayOfYear() >= 1) {
                        return 2;
                    }

                    return 1;
                })
                .value();
        }

        /**
         * @method _setQueryStatus
         * @param {*} statuses 
         */
        function _setQueryStatus(statuses) {
            return { $in: statuses };
        }


        /**
         * @method _setStatuses
         * @param {*} statuses 
         */
        function _setStatuses(statuses) {
            if (statuses.length) {
                var arrFilter = [];
                if (statuses.indexOf(1) > -1 || statuses.indexOf(3) > -1) {
                    arrFilter.push("ABERTO");
                }
                if (statuses.indexOf(2) > -1) {
                    arrFilter.push("FECHADO");
                }

                return arrFilter;
            } else {
                return ["ABERTO", "FECHADO"];
            }
        }

        /**
         * @method _setTimeWindow
         * @param {*} timeWindow 
         */
        function _setTimeWindow(timeWindow) {
            if (timeWindow == null || timeWindow == undefined) {
                timeWindow = {
                    start: moment().startOf('day').subtract(1, 'day').format(),
                    end: moment().endOf('day').format()
                };
            }
            var newTimeWindow = {
                start: timeWindow.start,
                end: timeWindow.end
            };

            //Converto para o formato dd/mm/yyyy antes
            //de formatar para o formato padrão que é o que o backend entende.
            if (newTimeWindow.start.indexOf('T') > -1) {
                newTimeWindow.start = moment(newTimeWindow.start).format('DD/MM/YYYY HH:mm');
            }
            newTimeWindow.start = moment(newTimeWindow.start, 'DD/MM/YYYY HH:mm').format();

            if (newTimeWindow.end.indexOf('T') > -1) {
                newTimeWindow.end = moment(newTimeWindow.end).format('DD/MM/YYYY HH:mm');
            }
            newTimeWindow.end = moment(newTimeWindow.end, 'DD/MM/YYYY HH:mm').format();

            return newTimeWindow;
        }

        /**
         * @method _filtrarAtivos
         * @param {*} dataArr 
         * @param {*} filterString 
         */
        function _filtrarAtivos(dataArr, filterString) {
            return _.chain(dataArr)
                .filter('ativo')
                .map(filterString)
                .value();
        }

        /**
         * @method _setQueryGravidadeIncidenteId
         * @param {*} gravidades 
         */
        function _setQueryGravidadeIncidenteId(gravidades) {
            var ativos = _filtrarAtivos(gravidades, 'id');
            return (ativos.length) ? { $in: ativos } : { $in: [] };
        }

        /**
         * @method _setQueryTipoIncidenteId
         * @param {*} tipoIncidentes 
         */
        function _setQueryTipoIncidenteId(tipoIncidentes) {
            var ativos = _filtrarAtivos(tipoIncidentes, 'id');
            return (ativos.length) ? { $in: ativos } : { $in: [] };
        }

        /**
         * @method _setQueryTimeWindow
         * @param {*} timeWindow 
         */
        function _setQueryTimeWindow(timeWindow) {
            return {
                $between: [
                    timeWindow.start,
                    timeWindow.end
                ]
            };
        }

        /**
         * @method _setQueryCategoria
         * @param {*} categorias 
         */
        function _setQueryCategoria(categorias) {

            if ($scope.moduleFilter.agencia && $scope.moduleFilter.agencia != '') {
                var agencias = [];
                agencias.push($scope.moduleFilter.agencia);
                return { $in: agencias };
            }

            if (categorias.length) {
                return { $in: _filtrarAtivos(categorias, 'id') };
            }
            return;
        }

        var statuses = [];
        /**
         * @method _setQuery
         * @param {*} filterData 
         */
        function _setQuery(filterData) {
            var data = {};
            var timeWindow = _setTimeWindow(filterData.timeWindow, _filtrarAtivos(filterData.statuses, 'id'));
            statuses = _setStatuses(_filtrarAtivos(filterData.statuses, 'id'));

            data.status = _setQueryStatus(statuses);
            data.CategoriaIncidenteId = _setQueryCategoria(filterData.categorias);
            data.GravidadeIncidenteId = _setQueryGravidadeIncidenteId(filterData.gravidades);
            data.TipoIncidenteId = _setQueryTipoIncidenteId(filterData.tipoIncidentes);
            data.inicio = _setQueryTimeWindow(timeWindow);
            data.searchText = $scope.searchText;

            return {
                where: data,
                include: 'CategoriaIncidente'
            };
        };

        /**
         * @method setQuery
         */
        function setQuery() {
            var filterData = _getFilterData();
            var data = {};
            var timeWindow = _setTimeWindow(filterData.timeWindow, _filtrarAtivos(filterData.statuses, 'id'));
            statuses = _setStatuses(_filtrarAtivos(filterData.statuses, 'id'));

            data.status = _setQueryStatus(statuses);
            data.CategoriaIncidenteId = _setQueryCategoria(filterData.categorias);
            data.GravidadeIncidenteId = _setQueryGravidadeIncidenteId(filterData.gravidades);
            data.TipoIncidenteId = _setQueryTipoIncidenteId(filterData.tipoIncidentes);
            data.inicio = _setQueryTimeWindow(timeWindow);

            return {
                where: data,
                include: {
                    model: 'GrupoUsuarios',
                    'as': 'GruposUsuarios',
                    include: {
                        model: 'Usuario'
                    },
                    where: {
                        id: {
                            $in: _.chain(filterData.gruposUSuarios)
                                .filter('ativo')
                                .map('id')
                                .value()
                        }
                    }
                },
                order: 'inicio DESC'

            };
        };

        $scope.exportToPdf = function () {

            var ids = $scope.incidentesGrid.data.map(function (incidente) {
                return incidente.id;
            });

            if (ids.length) {

                IncidentesService.getPdfReport(ids)
                    .then(function (data) {
                        var file = new Blob([data], { type: 'application/pdf' });
                        var fileURL = URL.createObjectURL(file);
                        var a = document.createElement("a");
                        document.body.appendChild(a);
                        a.style = "display: none";
                        a.href = fileURL;
                        a.download = $scope.res('Incidentes') + ".pdf";
                        a.click();

                        $mdDialog
                            .show($mdDialog.alert()
                                .title($scope.res('COMUM_SUCESSO'))
                                .content('Arquivo gerado com sucesso.')
                                .ok($scope.res('COMUM_OK')));
                    });

            } else {

                $mdDialog
                    .show($mdDialog.alert()
                        .title($scope.res('COMUM_AVISO'))
                        .content($scope.res('SEM_INCIDENTES'))
                        .ok('OK'));
            }
        };

        /**
         * @method exportarExcel
         */
        $scope.exportarExcel = function () {
            var data = {};
            data.incidentes = $scope.incidentesGrid.data.map(function (incidente) {
                return incidente;
            });
            if (data.incidentes.length) {

                data.headers = [$scope.res('MSI_NOME'), $scope.res('COMUM_DESCRICAO'), $scope.res('COMUM_ORIGEM_SINGULAR'),
                $scope.res('MSI_TIPODEINCIDENTE'), $scope.res('DETALHAMENTO_STATUS'), $scope.res('INCIDENTE_GRAVIDADE'),
                $scope.res('INCIDENTE_AUTOR'), $scope.res('INCIDENTE_RESPONSAVEL'), $scope.res('DETALHAMENTO_DATAHORA'), $scope.res('DETALHAMENTO_LOCAL')];

                $http
                    .post(API_ENDPOINT + 'dashboard/incidentes/excel', data, { responseType: 'arraybuffer', })
                    .then(function (res) {

                        var a = document.createElement("a");
                        document.body.appendChild(a);
                        a.style = "display: none";

                        var file = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
                        var fileURL = URL.createObjectURL(file);

                        a.href = fileURL;
                        a.download = $scope.res('Incidentes') + ".xlsx";
                        a.click();

                        $mdDialog
                            .show($mdDialog.alert()
                                .title($scope.res('COMUM_SUCESSO'))
                                .content('Arquivo gerado com sucesso.')
                                .ok($scope.res('COMUM_OK')));
                    }, function (err) {
                        console.log(err);
                    });

            } else {

                $mdDialog
                    .show($mdDialog.alert()
                        .title($scope.res('COMUM_AVISO'))
                        .content($scope.res('SEM_INCIDENTES'))
                        .ok('OK'));
            }
        }

        /**
         * @method _getFilterData
         */
        function _getFilterData() {

            var filter = MainState.getDirective('msiFilter');

            return {
                categorias: filter.categorias,
                gruposUsuarios: filter.gruposUsuarios,
                tipoIncidentes: filter.tipoIncidentes,
                statuses: filter.statuses,
                gravidades: filter.gravidades,
                timeWindow: filter.dataRange
            };
        }

        $scope.incidenteAtivo = -1;

        $scope.abrirDetalhamento = function (incidente) {
            DetalhamentoManager.abrirIncidente(incidente.id, {
                lat: incidente.geometry.coordinates[1],
                lng: incidente.geometry.coordinates[0]
            });
        };

        var lastIncident;
        /**
         * @method voarIncidente
         */
        $scope.voarIncidente = function (incidente, naoCarrega) {

            if (incidente == lastIncident) {
                return;
            }

            lastIncident = incidente;

            var ponto = {
                lat: incidente.geometry.coordinates[1],
                lng: incidente.geometry.coordinates[0]
            };


            IncidentesService
                .pegarCamerasProximas(ponto)
                .then(function (data) {
                    if (data.length) {
                        IncidentesManager.abrirMosaicoCameras(ponto, data);
                    }
                    else { // Se não tem nenhuma câmera nas proximidades, defino o zoom no incidente selecionado.
                        MapaService.setView(ponto, 15);
                    }
                    $scope.camerasProximas = data;
                });

            MapaService.piscarVermelho(ponto);
            if (!naoCarrega) {
                CamadasService.ativarMenuDoIncidente(incidente);
            }

        };

        $scope.abrirDetalhes = function (incidente) {
            MsiService.incidenteDetalhamento.incidente = incidente;
            MsiService.state.isVisible = true;
        };

        $scope.timestamp2string = timestamp2string;

        /**
         * @method timestamp2string
         * @param {*} timestamp 
         */
        function timestamp2string(timestamp) {
            if (timestamp === null) {
                return;
            }

            var date = new Date(timestamp);
            var mom = moment(date);
            var formattedDate = mom.format();
            return formattedDate;
        }

        /**
         * @method gotoIncidente
         * @param {*} x 
         */
        function gotoIncidente(x) {

            $scope.incidenteAtivo = x;
            $anchorScroll();
        }

        /**
         * @method setModuloMsiFechado
         * @param {*} value 
         */
        function setModuloMsiFechado(value) {
            $scope.moduloMsiFechado = value;
        }

        /**
         * @method msiFechado
         */
        function msiFechado() {
            if ($scope.moduloMsiFechado) {
                return true;
            }

            return false;
        }

        /**
         * Cuidado ao mexer neste código.
         */
        $scope.hasResults = true;
        var maxVerticalScroll = 0;
        var lastMaxVerticalScroll = 1;
        var viewPort = undefined;
        $timeout(function () {

            $('#msi-rows div.ui-grid-viewport').on('scroll', function () {

                if (!viewPort) {
                    viewPort = getViewPort();

                    if (!viewPort) {
                        return;
                    }
                }

                maxVerticalScroll = viewPort.scrollHeight - viewPort.clientHeight;
                var currentVerticalScroll = viewPort.scrollTop;

                if (maxVerticalScroll > 0 && currentVerticalScroll >= (maxVerticalScroll - 12) && $scope.hasResults && lastMaxVerticalScroll != maxVerticalScroll) {
                    $scope.pageNumber = $scope.pageNumber + 1;
                    loadIncidentes();
                    lastMaxVerticalScroll = maxVerticalScroll;
                }
            });
        });

        /**
         * @method getViewPort
         */
        function getViewPort() {
            for (var index in $('#msi-rows div.ui-grid-viewport')) {
                if ($('#msi-rows div.ui-grid-viewport')[index].scrollHeight > 0) {
                    return $('#msi-rows div.ui-grid-viewport')[index];
                }
            }
        }

        /**
         * @method clearAll
         */
        function clearAll() {
            $scope.incidentes = [];
            loadTable($scope.incidentes);
        }

        angular.extend($scope, {
            $apimsi: {
                gotoIncidente: gotoIncidente,
                refreshIncidentes: loadIncidentes,
                setQuery: setQuery,
                carregarLayerIncidentes: carregarLayerIncidentes,
                setModuloMsiFechado: setModuloMsiFechado,
                removerCamadas: removerCamadas,
                adicionaNovoIncidenteManual: adicionaNovoIncidenteManual,
                msiFechado: msiFechado,
                voarIncidente: $scope.voarIncidente,
                addIncidente: addIncidente,
                showInMap: showInMap,
                atualizaIncidente: atualizaIncidente,
                clearAll: clearAll
            }
        });

        if (MainState.getDirective($attrs.id)) {
            MainState.getDirective($attrs.id).clearAll();
            MainState.unregisterDirective($attrs.id);
        }
        MainState.registerDirective($attrs.id, $scope.$apimsi);
    }

    function s4cMsi() {
        return {
            restrict: 'EA',
            templateUrl: 'app/directives/msi/msi.html',
            controller: msiController
        };
    }

    angular.module('s4c.components.msi')
        .directive('s4cMsi', s4cMsi);
})();