Source: directives/incidentes/incidentes.js

/**
 * @ngdoc directives
 * @name Incidentes
 * @module s4c.directives.incidentes.incidentes
 *
 * @description
 * `s4c-incidentes` exibe informações sobre incidentes inseridos no Fusion
 *
 *@example
 *   <s4c-incidentes></s4c-incidentes>
 *
 */
(function () {
    'use strict';

    angular.module('s4c.components.incidentes')
        .directive('s4cIncidentes', s4cIncidentes)
        .filter('filtroAgencias', function () {
            return function (agencias) {
                if (!agencias || agencias.length <= 0) {
                    return '-';
                } else {
                    var _agencias = _.chain(agencias)
                        .filter(function (agencia) {
                            return agencia.ativo;
                        })
                        .map('nome')
                        .value();

                    if (_agencias.length > 0) {
                        return _agencias.join(', ');
                    } else {
                        return '-';
                    }

                }
            };
        })
        .filter('filtroPrioridades', function () {
            return function (prioridades) {
                if (prioridades.length <= 0) {
                    return '-';
                } else {
                    return prioridades.join(', ');
                }
            };
        })
        .filter('filtroOrigem', function () {

            return function (items, filters) {
                if (!filters) {
                    return items;
                }

                return _.filter(items, function (incidente) {
                    if (!incidente.extras) {
                        return false;
                    }

                    var categoriasPermitidas = _.chain(filters.categorias)
                        .filter(function (categoria) {
                            return categoria.ativo;
                        })
                        .map('id')
                        .value();

                    if (categoriasPermitidas.indexOf(incidente.CategoriaIncidenteId) < 0) {
                        return false;
                    }

                    if (incidente.extras.informacoes) {

                        // Encontrando prioridade:
                        var prioridade = _.find(incidente.extras.informacoes, function (informacao) {
                            return informacao.label === 'Prioridade';
                        });

                        var criticidade = _.find(incidente.extras.informaceos, function (informacao) {
                            return informacao.label === 'Criticidade';
                        });

                        if (prioridade) {
                            return filters.prioridades.indexOf(prioridade.valor) > -1;
                        }

                        if (criticidade) {
                            return filters.criticidades.indexOf(criticidade.valor) > -1;
                        }
                    }

                    return false;
                });
            };
        });

    incidentesCtrl.$inject = [
        '$scope',
        '$timeout',
        'IncidentesService',
        'CommService',
        'IncidenteFilter',
        'CamadasService',
        'MainState',
        'IncidentesManager',
        'AuthService',
        'DetalhamentoManager',
        'localize',
        '$rootScope'
    ];

    function s4cIncidentes() {

        return {
            restrict: 'AE',
            templateUrl: 'app/directives/incidentes/incidentes.html',
            controller: incidentesCtrl,
            transclude: true,
            scope: {
                filters: '=data'
            },
            link: function ($scope, $elem, $attrs) {
                $scope.incidentes = [];
            }
        };
    }

    function incidentesCtrl($scope,
        $timeout,
        IncidentesService,
        CommService,
        IncidenteFilter,
        CamadasService,
        MainState,
        IncidentesManager,
        AuthService,
        DetalhamentoManager,
        localize,
        $rootScope) {

        $scope.res = $rootScope.res;

        var filterInstance = IncidenteFilter.getInstance('filtro-incidentes');

        filterInstance.pagination = {
            limit: 5000,
            offset: 0,
            end: false,
            nextPage: function () {
                this.offset += this.limit;
                return this.begin;
            },
            reset: function () {
                this.offset = 0;
                this.end = false;
            },
            showMore: function () {
                this.nextPage();
                filterInstance.trigger('filterChanged', filterInstance.origem);
            }
        };

        $scope.showMore = function () {
            if (!filterInstance.pagination.end) {
                filterInstance.pagination.showMore();
            }
        }

        $scope.incidentes = [];
        $scope.pegarCameras = pegarCameras;
        $scope.IncidentesManager = IncidentesManager;

        /**
         * Listener para aplicação da inclusão de incidente na lista de incidentes disparados de outros componentes
         * 
         * @method incidentes_
         * 
         * @param incidente {Object} 
         * 
         */          
        CommService.on('incidentes_', function (incidente) {
            var incidenteAntigo = _obterIncidente(incidente);
            if (incidenteAntigo) {
                $scope.$apply(function () {
                    if (_filtrarIncidente(incidente)) {
                        _.chain(incidente)
                            .keys()
                            .each(function (key) {
                                incidenteAntigo[key] = incidente[key];
                            })
                            .value()
                        parseIncidente(incidenteAntigo);
                        // Camadas Already do this
                        // CamadasService.atualizarIconeIncidente(incidente);
                    } else {
                        $scope.incidentes = [];
                    }
                });
            } else {
                if (_filtrarIncidente(incidente)) {
                    $scope.$apply(function () {
                        $scope.incidentes.push(parseIncidente(incidente));
                    });
                }
            }

            DetalhamentoManager.fechar();
        });

        /**
         * Listener para aplicação da remoção de incidente da lista de incidentes disparados de outros componentes
         * 
         * @method removeIncidentes_
         * 
         * @param incidente {Object} 
         * 
         */           
        CommService.on('removeIncidentes_', function (incidente) {
            var incidenteAntigo = _obterIncidente(incidente);
            if (incidenteAntigo) {
                $scope.$apply(function () {
                    $scope.incidentes.splice($scope.incidentes.indexOf(incidenteAntigo), 1);
                    DetalhamentoManager.fechar();
                });
            }
        });

        /**
         * Listener para aplicação da atualização da lista de incidentes disparados de outros componentes
         * 
         * @method filterChanged
         * 
         */          
        IncidenteFilter.getInstance('filtro-incidentes').on('filterChanged', _reloadIncidentes);


        /**
         * Listener para aplicação do filtro disparados de outros componentes
         * 
         * @method filterChangedMenu
         * 
         * @param array {Array} 
         * 
         */  
        IncidenteFilter.getInstance('filtro-incidentes').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) {
                filterInstance.pagination.reset();
                $scope.incidentes = [];
            } else {
                filterInstance.pagination.reset();
                $scope.incidentes = incidentesAntigos;
            }

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

            if (novosIncidentes != null && novosIncidentes.length < filterInstance.pagination.limit) {
                filterInstance.pagination.end = true;
            }
            if (incidentesList != null) {
                $scope.incidentes = _filterAfterQuery(incidentesList);
            }
            $scope.nothingFound = (!$scope.incidentes.length);
        });

        $scope.voarIncidente = function (incidente) {
            if (typeof incidente.geojson === 'string') {
                incidente.geojson = JSON.parse(incidente.geojson);
            }

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

            $scope.pegarCameras(point);
            //MainState.managers.MapaManager.voarParaObjeto(incidente);
            MainState.managers.MapaManager.piscarVermelho(point);

            if (incidente.Poi) {
                CamadasService.ativarMenuPoi(incidente.Poi);
            } else {
                CamadasService.ativarMenuDoIncidente(incidente)
            }
        };

        /**
         * Aplica o filtro
         * 
         * @method _filtrarIncidente
         * 
         * @param incidente {Object} 
         * 
         */     
        function _filtrarIncidente(incidente) {
            return IncidenteFilter.getInstance('filtro-incidentes').filtrarIncidente(incidente);
        }


        /**
         * Busca as câmeras próximas ao Incidente
         * 
         * @method pegarCameras
         * 
         * @param ponto {Object} 
         * 
         */        
        function pegarCameras(ponto) {
            IncidentesService
                .pegarCamerasProximas(ponto)
                .then(function (data) {
                    if (data.length) {
                        MainState.managers.IncidentesManager.abrirMosaicoCameras(ponto, data);
                    }
                    $scope.camerasProximas = data;
                });
        }

        /**
         * Busca Incidente com a chave estrangeira como parâmetro 
         * 
         * @method _obterIncidente
         * 
         * @param incidente {Object} 
         * 
         * @returns Retorna os Incidentes encontrados
         */          
        function _obterIncidente(incidente) {
            return _.find($scope.incidentes, { chave_estrangeira: incidente.chave_estrangeira });
        }

        /**
         * Atualiza o mapa carregando os novos incidentes
         * 
         * @method _updateCamadasService
         * 
         */        
        function _updateCamadasService() {

            var filterData = _getFilterData();
            var categorias = filterData.categorias;
            var statuses = filterData.statuses;

            var itensParaDesativar = [];

            _.each(categorias, function (categoria) {
                _.each(statuses, function (status) {
                    if (status.ativo && categoria.ativo) {
                        CamadasService.ativarSubMenuStatusIncidente(categoria.id, status.nome);
                    } else {
                        itensParaDesativar.push({
                            categoriaId: categoria.id,
                            status: status.nome
                        });
                    }
                });
            });

            _.each(itensParaDesativar, function (item) {
                CamadasService.desativarSubMenuStatusIncidente(item.categoriaId, item.status, {
                    origem: 'filtro'
                });
            });
        }

        /**
         * Retorna os Incidentes com status ativo
         * 
         * @method _filtrarAtivos
         * 
         * @param dataArr {Array} Lista de Incidentes
         * @param filterString {String}
         * 
         * @returns Retorna os Incidentes com status ativo
         */        
        function _filtrarAtivos(dataArr, filterString) {
            return _.chain(dataArr)
                .filter('ativo')
                .map(filterString)
                .value();
        }

        /**
         * Aplica o filtro de Gravidades de Incidentes
         * 
         * @method _setQueryGravidadeIncidenteId
         * 
         * @param gravidades {Object}
         * 
         * @returns retorna os Incidentes com o filtro de Gravidades de Incidentes aplicados
         */        
        function _setQueryGravidadeIncidenteId(gravidades) {
            var ativos = _filtrarAtivos(gravidades, 'id');
            return (ativos.length) ? { $in: ativos } : null;
        }

        /**
         * Aplica o filtro de tipo de incidentes
         * 
         * @method _setQueryTipoIncidenteId
         * 
         * @param tipoIncidentes {Object}
         * 
         * @returns retorna os Incidentes com o filtro de tipos de incidentes aplicados
         */          
        function _setQueryTipoIncidenteId(tipoIncidentes) {
            var ativos = _filtrarAtivos(tipoIncidentes, 'id');
            return (ativos.length) ? { $in: ativos } : null;
        }


        /**
         * Inclui data de início e fim
         * 
         * @method _setQueryTimeWindow
         * 
         * @param timeWindow {Date}
         * 
         * @returns retorna as datas parametrizados no formato de query
         */          
        function _setQueryTimeWindow(timeWindow) {
            return {
                $between: [
                    timeWindow.start,
                    timeWindow.end
                ]
            };
        }

        /* Statuses: 1. Aberto 2. Fechado 3. Aberto 24h */
        /**
         * Inclui os status no objeto que serve de query
         * Statuses: 1. Aberto 2. Fechado 3. Aberto 24h 
         * 
         * @method _setQueryStatus
         * 
         * @param statuses {String}
         * 
         * @returns retorna os status parametrizados no formato de query
         */            
        function _setQueryStatus(statuses) {
            return { $in: statuses };
        }

        /**
         * Seta os status em um array que será retornado
         * 
         * @method _setStatuses
         * 
         * @param _setStatuses {String}
         * 
         * @returns retorna os status
         */         
        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"];
            }
        }

        /**
         * Retorna os campos de data de início e fim
         * 
         * @method _setQueryCategoria
         * 
         * @param timeWindow {Object}
         * 
         * @returns Retorna os campos de data de início e fim
         */            
        function _setTimeWindow(timeWindow) {
            var newTimeWindow = {
                start: timeWindow.start,
                end: timeWindow.end
            };

            newTimeWindow.start = moment(newTimeWindow.start).format();
            newTimeWindow.end = moment(newTimeWindow.end).format();

            return newTimeWindow;
        }

        /**
         * Aplicação dos filtros de categoria
         * 
         * @method _setQueryCategoria
         * 
         * @param categorias {Object}
         * 
         * @returns retorna os Incidentes com o filtro de Categorias aplicados
         */           
        function _setQueryCategoria(categorias) {
            if (categorias.length) {
                return { $in: _filtrarAtivos(categorias, 'id') };
            }
            return;
        }

        /**
         * Formatação do Objeto que será passado para o backend para aplicação do Filtro 
         * 
         * @method setQuery
         * 
         * @returns Objeto com os parâmetros que serão usados para aplicação do filtro
         *
         */          
        function setQuery() {
            var filterData = _getFilterData();
            var data = {};
            var timeWindow = _setTimeWindow(filterData.timeWindow);
            var 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);

            // Deletes invalid filters
            for (var filtro in data) {
                if (data.hasOwnProperty(filtro) && (data[filtro] === null) || data[filtro] === undefined) {
                    delete data[filtro];
                }
            }

            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',
                limit: filterInstance.pagination.limit,
                offset: filterInstance.pagination.offset
            };
        };

        /**
         * Retorna os campos do filtro 
         * 
         * @method _getFilterData
         * 
         * @returns Retorna os campos do filtro
         *
         */          
        function _getFilterData() {
            return {
                categorias: IncidenteFilter.getInstance('filtro-incidentes').categorias,
                gruposUsuarios: IncidenteFilter.getInstance('filtro-incidentes').gruposUsuarios,
                tipoIncidentes: IncidenteFilter.getInstance('filtro-incidentes').tipoIncidentes,
                statuses: IncidenteFilter.getInstance('filtro-incidentes').statuses,
                gravidades: IncidenteFilter.getInstance('filtro-incidentes').gravidades,
                timeWindow: IncidenteFilter.getInstance('filtro-incidentes').dataRange
            };
        }

        /**
         * Verifica se o menuCamada já está carregado
         * 
         * @method verificaMenuCarregado
         *
         */          
        function verificaMenuCarregado() {
            if (!CamadasService.isLoaded) {
                setTimeout(function () {
                    verificaMenuCarregado();
                }, 1000);
            } else {
                _updateCamadasService();
            }
        }

        /**
         * Recarrega a lista de Incidentes
         * 
         * @method _reloadIncidentes
         *
         * @param origem {Object}
         *
         * 
         */             
        function _reloadIncidentes(origem) {
            if (origem === 'filtro') {
                filterInstance.pagination.reset();
                $scope.incidentes = [];
            }
            var query = setQuery();

            verificaMenuCarregado();

            IncidentesService.findByFilter(query)
                .then(function (incidentes) {
                    var novosIncidentes = incidentes;
                    var incidentesList = $scope.incidentes.concat(novosIncidentes);

                    if (novosIncidentes.length < filterInstance.pagination.limit) {
                        filterInstance.pagination.end = true;
                    }

                    $scope.incidentes = _filterAfterQuery(incidentesList);
                    if ($scope.incidentes != null && $scope.incidentes.length > 0) {
                        $scope.nothingFound = true;
                    } else {
                        $scope.nothingFound = false;
                    }

                });
        }

        /**
         * Filtra os Incidentes pela prioridade
         * 
         * @method _filterAfterQuery
         *
         * @param incidentes {Object}
         *
         * 
         */          
        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) {
                    var prioridade = obj.extras.informacoes.filter(function (item, i) {
                        if (item.label === 'Prioridade') {
                            delete obj.extras.informacoes[i];
                        }
                    });
                }
            });

            return newIncidentes;
        }

        // 
        /**
         * Filtra os Incidentes pelo Status
         * 1. Aberto 2. Fechado 3. Aberto 24h
         * 
         * @method _formatDataIncidenteToString
         *
         * @param dataInicio {Object}
         * @param dataFim {Object}   
         *
         */          
        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;
        }

        /**
         * Faz a formatação da data
         * 
         * @method _formatDataIncidenteToString
         *
         * @param dataInicio {Object}
         * @param dataFim {Object}   
         *
         */         
        function _formatDataIncidenteToString(dataInicio, dataFim) {
            var dataString = '';

            /* Início do incidente menor que a data do Fim */
            if (dataInicio.dayOfYear() < dataFim.dayOfYear()) {
                dataString = dataInicio.format('HH:mm');
                dataString += dataInicio.format(' (MMM D)');
                dataString += ' - ';
                dataString += dataFim.format('HH:mm');
                dataString += dataFim.format(' (MMM D)');
            }

            /* Início do incidente igual a data do Fim */
            if (dataInicio.dayOfYear() === dataFim.dayOfYear()) {
                dataString = dataInicio.format('HH:mm');
                dataString += ' - ';
                dataString += dataFim.format('HH:mm');
            }

            return dataString;
        }

        /**
         * Faz o parse do Incidente
         * 
         * @method parseIncidente
         *
         * @param incidente {Object} 
         *
         */          
        function parseIncidente(incidente) {
            var data = '';
            var icons = {
                green: '/data-s4c/teste/ic_incidentes_green_26px.svg',
                red: '/data-s4c/teste/ic_incidentes_grey_26px.svg',
                purple: '/data-s4c/teste/ic_incidentes_purple_24px.svg'
            };
            incidente.icon = icons.green; // Default icon


            /* Formata o Início e o Fim */
            if (incidente.inicio) {
                incidente.inicio = moment(moment(incidente.inicio).toDate());
            }

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

            if (incidente.inicio && incidente.fim) {
                data = _formatDataIncidenteToString(incidente.inicio, incidente.fim);
            }

            var gravidades = IncidenteFilter.getInstance('filtro-incidentes').gravidades;

            incidente.gravidade = _.find(gravidades, { id: incidente.GravidadeIncidenteId });

            if (incidente.status === 'ABERTO') {
                incidente.icon = icons.red;
                if (incidente.inicio) {
                    data = incidente.inicio.format('DD/MM/YYYY - HH:mm');
                    //if (moment().dayOfYear() > incidente.inicio.dayOfYear()) {
                    //   data += incidente.inicio.format(' (MMM D)');
                    //}
                }

                if (incidente.inicio.dayOfYear() < moment().dayOfYear()) {
                    incidente.icon = icons.purple;
                    incidente.urlIcone = incidente.urlIcone.replace('vermelho', 'purple');
                }
            }

            if (incidente.status === 'FECHADO') {
                incidente.urlIcone = incidente.urlIconeFechado || (incidente.TipoIncidente && incidente.TipoIncidente.urlIconeFechado) || incidente.CategoriaIncidente.urlIconeFechado;

                if (incidente.fim && incidente.inicio) {
                    if (moment().dayOfYear() > incidente.fim.dayOfYear()) {
                        incidente.icon = icons.purple;
                        incidente.urlIcone = incidente.urlIcone.replace('vermelho', 'purple');
                    }
                }
            }

            incidente.data = data;
            return incidente;
        }

        /**
         * Recarrega a lista de Incidentes
         * 
         * @method initFilter
         *
         */         
        function refreshIncidentes() {
            _reloadIncidentes('filtro');
        }

        /**
         * Formata a data de inicio e fim. Para que as datas sejam sempre de as 00:00 de ontem até as 23:59 de hoje
         * 
         * @method _timeSet
         *
         *
         */           
        function _timeSet() {
            return {
                start: moment().subtract(1, 'day').startOf('day').format(),
                end: moment().endOf('day').format()
            }
        };

        /**
         * Inicializa o filtro
         * 
         * @method initFilter
         *
         */          
        function initFilter() {
            IncidenteFilter.getInstance('filtro-incidentes').dataRange = _timeSet();
        }

        MainState.registerDirective('incidentes', {
            refreshIncidentes: refreshIncidentes,
            setQuery: setQuery,
            initFilter: initFilter
        });

        //$timeout(function() {
        //IncidenteFilter.getInstance('filtro-incidentes').trigger('filterChanged');
        //$scope.incidentes = IncidentesService.incidentes;
        refreshIncidentes();
        //}, 100);

    }
}());