Source: directives/busca/busca.js

    /**
     * @ngdoc directives
     * @name busca
     * @module s4c.directives.busca.BuscaService
     *
     * @description
     * `buscaCtrl` Caixa de busca do sistema, gerencia os resultados da barra
     * de busca.
     *
     * @example
     *   <s4c-busca>
     *   </s4c-busca>
     */
(function () {

    'use strict';

    buscaCtrl.$inject = [
        '$scope',
        '$rootScope',
        'BuscaService',
        'RotasService',
        'MainState',
        'CamadasService',
        'MapaManager',
        'localize',
        'ZonaObservacaoService',
        'ZonaDeObservacaoManager',
        'RotasUnificadasService',
        'RotasUnificadasManager',
        'DetalhamentoManager',
        'SubDetalhamentoManager',
        'BaseConhecimentoManager',
        'BaseConhecimentoService',
        'PlanejamentoManager',
        'PlanejamentoService',
        'CamerasManager',
        'RepresentacaoService',
        'MapaService'
    ];


    function buscaCtrl($scope,
        $rootScope,
        BuscaService,
        RotasService,
        MainState,
        CamadasService,
        MapaManager,
        localize,
        ZonaObservacaoService,
        ZonaDeObservacaoManager,
        RotasUnificadasService,
        RotasUnificadasManager,
        DetalhamentoManager,
        SubDetalhamentoManager,
        BaseConhecimentoManager,
        BaseConhecimentoService,
        PlanejamentoManager,
        PlanejamentoService,
        CamerasManager,
        RepresentacaoService,
        MapaService) {

        $scope.res = $rootScope.res;

        $scope.voarParaEndereco = function (endereco) {
            var MapaManager = MainState.getManager('MapaManager');
            MapaManager.alfineteLocalizacao({
                geojson: {
                    coordinates: [
                        endereco.geometry.location.B,
                        endereco.geometry.location.k
                    ]
                }
            });
        };

        $scope.$apiBusca = {
            getIconColor: getIconColor,
            search: search,
            getCategoryName: getCategoryName,
            executeSearch: executeSearch
        };

        $scope.abrirItem = abrirItem;
        $scope.showAdvancedResult = false;
        $scope.buscaModel = {};
        $scope.advancedResults = {};
        $scope.results = {};
        $scope.searchIcon = 'white';

        var hashAtivarCamada = {
            'zonaObservacao': function (result) {
                ZonaObservacaoService.pegarZona(result.id)
                    .then(function (zo) {
                        CamadasService.ativarMenuZonasDeObservacao();

                        var json = $.parseJSON(zo.poigeojson);

                        zo.poigeojson = json;

                        ZonaDeObservacaoManager.abrirExistente(zo);
                        zo.active = true;
                        var zonas = [];
                        zonas.push(zo);

                        CamadasService.filtrarZonasDeObservacao(zonas);
                        MapaManager.voarParaObjeto({
                            geojson: zo.geojson
                        });
                    });
            },
            'baseConhecimento': function (result) {

                BaseConhecimentoService.findById(result.id).then(function (base) {
                    if (base != null && base.id != null) {
                        CamadasService.exibirBasesConhecimento();

                        BaseConhecimentoManager.abrirDetalhamento(base);

                        MapaManager.voarParaObjeto({
                            geojson: result.geojson
                        });
                    }
                });
            },
            'incidentes': function (result) {
            	MainState.getDirective('filtro-msi').showInMap(result);
             },
            'planejamento': function(result) {
            	PlanejamentoService.getPlanejamento(result.id).then(function(planejamento){

	             		MapaManager.voarParaObjeto({
	             			geojson: planejamento.geojson
	                     });

                    	CamadasService.exibirPlanejamentos();

                    	PlanejamentoManager.abrir(planejamento);

            	});

            },
            'planejamento': function (result) {
                PlanejamentoService.getPlanejamento(result.id).then(function (planejamento) {

                    MapaManager.voarParaObjeto({
                        geojson: planejamento.geojson
                    });

                    CamadasService.exibirPlanejamentos();

                    PlanejamentoManager.abrir(planejamento);

                });

            },
            'localizacao': function (result) {
                MapaManager.voarParaObjeto({
                    geojson: result.geojson
                });
                MapaManager.alfineteLocalizacao(result);
            },
            'rotas': function (result) {
                RotasUnificadasService.pegarRota(result.id)
                    .then(function (rota) {
                        RotasUnificadasManager.editar(rota);
                        MapaManager.voarParaObjeto({
                            geojson: rota.shape
                        });
                    });
            },
            'pois': function (result) {
                CamadasService.ativarMenuPoi(result);
                var latlng = {};
                latlng.lat = result.latitude;
                latlng.lng = result.longitude;
                DetalhamentoManager.abrirPoi(result.id, latlng);

                if (result.geoson == null) {
                    result.geojson = turf.point([result.longitude, result.latitude]).geometry;
                }
                MapaManager.voarParaObjeto({
                    geojson: result.geojson,
                    geometry: result.geometry,
                    urlIcone: result.urlIcone
                });
            },
            'cameras': function (result) {
                CamadasService.ativarMenuDaCamera(result);

                MapaManager.voarParaObjeto({
                    geojson: result.geojson
                });
            },
            'viaturas': function (result) {
                result.geojson = turf.point([result.geo_point.lon, result.geo_point.lat]).geometry;

                MapaManager.voarParaObjeto({
                    geojson: result.geojson
                });

                result.viatura = true;

                CamadasService.ativarMenuViatura(result);

                DetalhamentoManager.abrirViatura(result);
            }
        }

       /**
        * Abre o item selecionado na busca  
        *
        * @method abrirItem
		*        
        * @param category {Object} Categoria do Item
        * @param result {Object} Resultado
		*               
        */ 
        function abrirItem(category, result) {
            if (hashAtivarCamada[category]) {
                hashAtivarCamada[category](result)
            }

            if (category == 'zonaObservacao') {
                if (result.poigeojson != null) {
                    result.geojson = result.poigeojson;
                } else {
                    ZonaObservacaoService.pegarZona(result.id).then(function (zo) {
                        result.geojson = zo.geojson;
                    });
                }
            }

            if (category == 'viaturas') {
                result.geojson = turf.point([result.posicao.longitude, result.posicao.latitude]);
            }
        }

       /**
        * Define a cor do Ícone  
        *
        * @method getIconColor
		*        
        * @param active {Boolean} Booleano com o status do icone
		*               
        */ 
        function getIconColor(active) {
            return (active) ? 'blue' : 'white';
        }

       /**
        * Obtem o nome da categoria  
        *
        * @method getCategoryName
		*        
        * @param category {Object} Categoria
		*               
        */ 
        function getCategoryName(category) {
            switch (category) {
                case 'localizacao':
                    return $scope.res('COMUM_LOCALIZACAO');
                case 'baseConhecimento':
                    return $scope.res('BASECONHECIMENTO_TITULO_PLURAL');
                case 'zonaObservacao':
                    return $scope.res('ZONAOBSERVACAO_TITULO_PLURAL');
                case 'planejamento':
                    return $scope.res('PLANEJAMENTO_TITULO_PLURAL');
                case 'rotas':
                    return $scope.res('ROTA_TITULO_PLURAL');
                case 'incidentes':
                    return $scope.res('INCIDENTE_TITULO_PLURAL');
                case 'pois':
                    return $scope.res('PONTOSDEINTERESSE_TITULO_PLURAL');
                case 'cameras':
                    return $scope.res('CAMERAS_TITULO');
                case 'viaturas':
                    return $scope.res('COMUM_ATIVOSMOVEIS');
                default:
                    return category;
            }
        }

       /**
        * Listener para o atributo buscaAtiva  
        *
        * @method watch
		*        
        * @param newVal {String} Novo Valor
		*               
        */ 
        $scope.$watch('buscaAtiva', function (newVal) {
            $scope.seletorAtivo = (newVal);
        });

       /**
        * Listener para o atributo texto do form buscaModel 
        *
        * @method watch
		*        
		*               
        */ 
        $scope.$watch('buscaModel.texto', function () {
            if (!$scope.buscaModel.texto) {
                MapaManager.removerAlfinete();
                MapaService.naoPiscar();
            }
        });

       /**
        * Listener para o atributo showAdvancedResult  
        *
        * @method watch
		*        
		*               
        */ 
        $scope.$watch('showAdvancedResult', function () {
            if (!$scope.showAdvancedResult) {
                MapaService.naoPiscar();
            }
        })

       /**
        * Desativa o resultado da busca  
        *
        * @method desativarBuscaResults
		*        
		*               
        */ 
        $scope.desativarBuscaResults = function () {
            setTimeout(function () {
                $scope.buscaResults = [];
            }, 400);
        };
        var ne = new google.maps.LatLng(-44.046739, -22.755719);
        var sw = new google.maps.LatLng(-43.046983, -23.131319);

       /**
        * Voa para o objeto selecionado 
        *
        * @method voarParaResult
		*        
        * @param result {String} Resultado com Lat, Lng
		*               
        */ 
        $scope.voarParaResult = function (result) {
            var MapaManager = MainState.getManager('MapaManager');
            MapaManager.voarParaObjeto({
                coordinates: [
                    result.geometry.location.lng(),
                    result.geometry.location.lat()
                ]
            });
            $scope.buscaResults = [];
        };

       /**
        * Obtem o tempo selecionado nos filtros 
        *
        * @method getTimeValue
		*        
        * @param timeFilters {String} Filtros de data
		*               
        */ 
        $scope.getTimeValue = function (timeFilters) {

            // moment().utc(moment().utcOffset()/60).unix() retorna em formato epoch, o data e hora do momento atual, em modo UTC, levando em consideração o offSet de timezone
            // moment().unix() retorna sempre em UTC 0, causando um desvio de três ou duas horas, se estivermos em horário de verão

            function filter(timeFilters) {
                if (timeFilters == $scope.res('BARRABUSCA_ULTIMAHORA')) {
                    startTime = moment().add(-1, 'hour').utc(moment().utcOffset() / 60).unix();
                    endTime = moment().utc(moment().utcOffset() / 60).unix();
                    return true;
                }
                if (timeFilters == $scope.res('BARRABUSCA_HOJE')) {
                    startTime = moment().startOf('day').utc(moment().utcOffset() / 60).unix();
                    endTime = moment().endOf('day').utc(moment().utcOffset() / 60).unix();
                    return true;
                }
                if (timeFilters == $scope.res('BARRABUSCA_ULTIMODIA')) {
                    startTime = moment().add(-1, 'day').startOf('day').utc(moment().utcOffset() / 60).unix();
                    endTime = moment().add(-1, 'day').endOf('day').utc(moment().utcOffset() / 60).unix();
                    return true;
                }
                if (timeFilters == $scope.res('BARRABUSCA_ULTIMASEMANA')) {
                    startTime = moment().add(-1, 'week').startOf('day').utc(moment().utcOffset() / 60).unix();
                    endTime = moment().add(-1, 'day').endOf('day').utc(moment().utcOffset() / 60).unix();
                    return true;
                }
                if (timeFilters == $scope.res('BARRABUSCA_ULTIMOMES')) {
                    startTime = moment().add(-1, 'month').startOf('day').utc(moment().utcOffset() / 60).unix();
                    endTime = moment().add(-1, 'day').endOf('day').utc(moment().utcOffset() / 60).unix();
                    return true;
                }
                if (timeFilters == $scope.res('BARRABUSCA_ULTIMOANO')) {
                    startTime = moment().add(-1, 'year').startOf('day').utc(moment().utcOffset() / 60).unix();
                    endTime = moment().add(-1, 'day').endOf('day').utc(moment().utcOffset() / 60).unix();
                    return true;
                }

                return false;
            };

            var startTime;
            var endTime;

            if (filter(timeFilters)) {
                $scope.buscaModel.end = endTime;
                $scope.buscaModel.start = startTime;
                return;
            } else {
                var dataFinal = moment(timeFilters.split(' - ')[1], 'DD/MM/YYYY hh:mm');
                var dataInicial = moment(timeFilters.split(' - ')[0], 'DD/MM/YYYY hh:mm');
                endTime = dataFinal.utc(moment().utcOffset() / 60).unix();
                startTime = dataInicial.utc(moment().utcOffset() / 60).unix();
            }

            $scope.buscaModel.end = endTime;
            $scope.buscaModel.start = startTime;
        };

        $scope.hasSearched = false;

       /**
        * Trata eventos simultaneos entre a lupa e o evento de click-outside do resultado da busca 
        *
        * @method search
		*        
        * @param $event {Object} Evento
		*               
        */         
        function search($event) {
            if ($event) {
                $scope.hasSearched = true;
            } else {

                if ($scope.hasSearched == true) {
                    $scope.hasSearched = false;
                } else {
                    $scope.showAdvancedResult = false;
                }

                return;
            }

            executeSearch();
        }

       /**
        * Executa a busca 
        *
        * @method executeSearch
		*        
		*               
        */       
        function executeSearch() {

            if ($scope.buscaModel.texto && $scope.buscaModel.texto.length > 0) {
                SubDetalhamentoManager.fechar();
                DetalhamentoManager.fechar();

                ZonaDeObservacaoManager.fechar();
                RotasUnificadasManager.fechar();

                $scope.showAdvancedResult = true;
                $scope.advancedResults = {};
                var BuscaManager = MainState.getManager('BuscaManager');
                var filters = _.filter(BuscaManager.getFilters(), 'active');
                var timeFilters = BuscaManager.getTimeFilters();

                if (timeFilters !== localize.getLocalizedString('BARRABUSCA_QUALQUERDIA')) {
                    $scope.getTimeValue(timeFilters)
                }
                else {
                    delete $scope.buscaModel.start;
                    delete $scope.buscaModel.end;
                }

                var hashBusca = {
                    '0': function () {

                        $scope.advancedResults.localizacao = {
                            carregando: true
                        };
                        var geocoder = new google.maps.Geocoder();
                        if ($scope.buscaModel.texto.length > 0) {
                            geocoder.geocode({
                                address: $scope.buscaModel.texto,
                                bounds: new google.maps.LatLngBounds(sw, ne)
                            }, function (response) {
                                $scope.advancedResults.localizacao.carregando = false;
                                var resultados = response.map(function (end) {
                                    return {
                                        nome: end.formatted_address,
                                        geojson: turf.point([
                                            end.geometry.location.lng(),
                                            end.geometry.location.lat()
                                        ]).geometry,
                                        urlIcone: '/assets/images/Consulta/ic_localizacao_white_24px.svg'
                                    };
                                });
                                $scope.advancedResults.localizacao.resultados = resultados;
                            });
                        } else {
                            $scope.advancedResults.localizacao.carregando = false;
                            $scope.advancedResults.localizacao.resultados = [];
                        }

                    },
                    '1': function () {
                        $scope.advancedResults.baseConhecimento = {
                            carregando: true
                        };
                        BuscaService.getBaseConhecimento($scope.buscaModel)
                            .then(function (data) {
                                $scope.advancedResults.baseConhecimento.carregando = false;
                                $scope.advancedResults.baseConhecimento.resultados = _.chain(data)
                                    .map(function (base) {
                                        base.urlIcone = '/assets/images/BaseDeConhecimento/ic_base_conhecimento_mapa_24px.png';
                                        base.inicio = moment(base.inicio).format("DD/MM/YYYY");
                                        return base;
                                    })
                                    .groupBy('id')
                                    .map(function (base) {
                                        return {
                                            data: base
                                        };
                                    })
                                    .value();
                            });
                    },
                    '2': function () {
                        $scope.advancedResults.planejamento = {
                            carregando: true
                        };
                        BuscaService.getPlanejamento($scope.buscaModel)
                            .then(function (data) {
                                $scope.advancedResults.planejamento.carregando = false;
                                $scope.advancedResults.planejamento.resultados = _.chain(data)
                                    .map(function (planejamento) {
                                        planejamento.urlIcone = '/assets/images/Planejamento/ic_maps_planejamento_48px.png';
                                        planejamento.inicio = moment(planejamento.inicio / 100 * 100).format("DD/MM/YYYY");

                                        return planejamento;
                                    })
                                    .groupBy('inicio')
                                    .map(function (planejamento) {
                                        return {
                                            inicio: planejamento[0].inicio,
                                            data: planejamento
                                        };
                                    })
                                    .value();
                            });
                    },
                    '3': function () {
                        $scope.advancedResults.zonaObservacao = {
                            carregando: true
                        };
                        BuscaService.getZonaObservacao($scope.buscaModel)
                            .then(function (data) {
                                $scope.advancedResults.zonaObservacao.carregando = false;
                                $scope.advancedResults.zonaObservacao.resultados = _.chain(data)
                                    .map(function (zo) {
                                        zo.urlIcone = '/assets/images/Datamining/ic_datamining_white_24px.svg';
                                        zo.inicio = moment(zo.inicio / 100 * 100).format("DD/MM/YYYY");

                                        return zo;
                                    })
                                    .groupBy('inicio')
                                    .map(function (zo) {
                                        return {
                                            inicio: zo[0].inicio,
                                            data: zo
                                        };
                                    })
                                    .value();
                            });
                    },
                    '4': function () {
                        $scope.advancedResults.rotas = {
                            carregando: true
                        };
                        BuscaService.getRotas($scope.buscaModel)
                            .then(function (data) {
                                $scope.advancedResults.rotas.carregando = false;
                                $scope.advancedResults.rotas.resultados = _.chain(data)
                                    .map(function (rota) {
                                        rota.urlIcone = '/assets/images/Consulta/ic_rotas_white_24px.svg';
                                        rota.inicio = moment(rota.inicio / 100 * 100).format("DD/MM/YYYY");

                                        return rota;
                                    })
                                    .groupBy('id')
                                    .map(function (rota) {
                                        return {
                                            data: rota
                                        };
                                    })
                                    .value();
                            });
                    },
                    '5': function () {
                        $scope.advancedResults.incidentes = {
                            carregando: true
                        };
                        BuscaService.getIncidentes($scope.buscaModel)
                            .then(function (data) {
                                $scope.advancedResults.incidentes.carregando = false;
                                $scope.advancedResults.incidentes.resultados = _.chain(data)
                                    .map(function (incidente) {

                                        incidente.filtro = $scope.res('COMUM_BUSCA');
                                        incidente.geojson = JSON.parse(incidente.geojson);
                                        incidente.geometry = incidente.geojson;
                                        incidente.urlIcone = incidente.urlIcone;
                                        incidente.inicio = moment(incidente.inicio, 'YYYY-MM-DD hh:mm').format("DD/MM/YYYY");

                                        var camporelativoArr = incidente.camporelativo.split(';');

                                        incidente.camporelativo = {
                                            field: camporelativoArr[0],
                                            value: camporelativoArr[1]
                                        };
                                        return incidente;
                                    })
                                    .groupBy('inicio')
                                    .map(function (incidente) {
                                        return {
                                            inicio: incidente[0].inicio,
                                            data: incidente
                                        };
                                    })
                                    .value();
                            });
                    },
                    '6': function () {
                        $scope.advancedResults.pois = {
                            carregando: true
                        };

                        if (filters.sensoresAtivos && filters.sensoresAtivos.length > 0) {
                            var sensoresAtivosId = _.map(filters.sensoresAtivos, 'acervoTipoId');
                            BuscaService.getPoisBySensores($scope.buscaModel, sensoresAtivosId)
                                .then(function (data) {
                                    $scope.advancedResults.pois.carregando = false;
                                    $scope.advancedResults.pois.resultados = data;
                                });
                        } else {
                            BuscaService.getPois($scope.buscaModel)
                                .then(function (data) {
                                    $scope.advancedResults.pois.carregando = false;
                                    $scope.advancedResults.pois.resultados = data;

                                    for (var key in $scope.advancedResults.pois.resultados) {
                                        if ($scope.advancedResults.pois.resultados[key].representacao && $scope.advancedResults.pois.resultados[key].extras) {
                                            $scope.advancedResults.pois.resultados[key].properties = { extras: $scope.advancedResults.pois.resultados[key].extras };
                                            $scope.advancedResults.pois.resultados[key].urlIcone =
                                                RepresentacaoService.getFunctionResult($scope.advancedResults.pois.resultados[key],
                                                    $scope.advancedResults.pois.resultados[key].representacao.json.pointLayout[0].circulo.centro.funcao);
                                        }
                                    }

                                });
                        }
                    },
                    '7': function () {
                        $scope.advancedResults.cameras = {
                            carregando: true
                        };
                        BuscaService.getCameras($scope.buscaModel)
                            .then(function (data) {
                                $scope.advancedResults.cameras.carregando = false;
                                $scope.advancedResults.cameras.resultados = _.map(data, function (camera) {
                                    camera.urlIcone = '/assets/images/Consulta/s4c_ic_camera_white_24px.svg';
                                    return camera;
                                });
                            });
                    },
                    '8': function () {
                        $scope.advancedResults.viaturas = {
                            carregando: true
                        };
                        BuscaService.getViaturas($scope.buscaModel)
                            .then(function (data) {
                                $scope.advancedResults.viaturas.carregando = false;
                                $scope.advancedResults.viaturas.resultados = _.map(data, function (viatura) {
                                    viatura.urlIcone = viatura.urlIcone ||
                                        '/data-s4c/Camadas/Viaturas/ic_maps_carro_policia6_48px.png';
                                    return viatura;
                                });
                            });
                    }
                }

                _.each(filters, function (filter) {
                    hashBusca[filter.indice]();
                });
            }
        }

        MainState.registerDirective('busca', $scope.$apiBusca);
        $scope.$on('$destroy', function () {
            MainState.unregisterDirective('busca');
        });
    }

    s4cBusca.$inject = [
        'MainState'
    ]

    function s4cBusca(MainState) {

        return {
            restrict: 'E',
            templateUrl: 'app/directives/busca/busca.html',
            replace: true,
            scope: {},
            controller: buscaCtrl,
            link: function ($scope, $elem, $attrs) {
                $scope.res = $scope.$root.res;
                MainState.registerDirective('busca', $scope.$apiBusca);

                $scope.$on('$destroy', function () {
                    MainState.unregisterDirective('busca');
                });


                var language;
                if ($scope.res("COMUM_LOCALE") == "pt-BR") {
                    language = 'pt-BR';
                } else {
                    language = 'en';
                }
                $scope.timeStep = 30;
                $scope.startDatetimepicker = $elem.find('#startDatetimepicker');
                $scope.startDatetimepicker.datetimepicker({
                    theme: 'dark',
                    format: 'd/m/Y H:i',
                    lang: language,
                    step: $scope.timeStep,
                    onChangeDateTime: function (dp, input) {
                        this.setOptions({
                            maxTime: $scope.buscaModel.fim ? (input.val().split(' ')[0] == $scope.buscaModel.fim.split(' ')[0] ? $scope.buscaModel.fim.split(' ')[1] : false) : false
                        });
                    },
                    onShow: function () {
                        this.setOptions({
                            maxDate: $scope.buscaModel.fim ? $scope.buscaModel.fim.split(' ')[0] : false,
                            formatDate: 'd.m.Y',
                        });
                    }
                });

                $scope.endDatetimepicker = $elem.find('#endDatetimepicker');
                $scope.endDatetimepicker.datetimepicker({
                    theme: 'dark',
                    format: 'd/m/Y H:i',
                    lang: language,
                    step: $scope.timeStep,
                    onChangeDateTime: function (dp, input) {
                        this.setOptions({
                            minTime: $scope.buscaModel.inicio ? (input.val().split(' ')[0] == $scope.buscaModel.inicio.split(' ')[0] ? $scope.buscaModel.inicio.split(' ')[1] : false) : false
                        });
                    },
                    onShow: function () {
                        this.setOptions({
                            minDate: $scope.buscaModel.inicio ? $scope.buscaModel.inicio.split(' ')[0] : false,
                            formatDate: 'd.m.Y',
                        });
                    }
                });
            }
        };
    }

   /**
    * Utilitário para busca de um texto em um outro campo passado como parametro 
    *
    * @method buscaItem
	*        
    */  
    function buscaItem() {
        return function (texto, buscaParam) {

            if (texto && buscaParam) {
                var index = texto.indexOf(buscaParam);
                if (index > -1) {
                    texto = texto.replace(
                        new RegExp('(' + buscaParam + ')', 'gi'),
                        '<b>$1</b>'
                    );
                }
            }

            return texto;
        };
    }

    angular.module('s4c.components.busca')
        .directive('s4cBusca', s4cBusca)
        .filter('buscaItem', buscaItem);

}());