Source: directives/adicionar-rotas-unificadas/adicionar-rotas-unificadas.js

/**
 * @ngdoc directives
 * @name adcionar-rotas-unificadas
 * @module s4c.directives.rotas-unificadas
 * 
 * @description `adicionarRotasUnificadasCtrl` mostra as informações de uma Rota
 *              existente no sistema ou informações de uma Rota sendo
 *              desenhada no momento.
 * 
 *@example <s4c-adicionar-rotas-unificadas> </s4c-adicionar-rotas-unificadas>
 */
(function () {
    'use strict';

    adicionarRotasUnificadasCtrl.$inject = ['$scope',
        '$state',
        'RotasUnificadasService',
        'MapaManager',
        'CamadasService',
        'IncidentesManager',
        'DetalhamentoManager',
        '$mdDialog',
        'Base',
        '$q',
        'MainState',
        'RotasUnificadasManager',
        'CommService',
        'RotasUnificadasFilter',
        'PermissoesService',
        'toasty',
        'Departamento',
        'MapaService',
        'FileUploader',
        'ngFileReader'];

    function adicionarRotasUnificadasCtrl($scope,
        $state,
        RotasUnificadasService,
        MapaManager,
        CamadasService,
        IncidentesManager,
        DetalhamentoManager,
        $mdDialog,
        Base,
        $q,
        MainState,
        RotasUnificadasManager,
        CommService,
        RotasUnificadasFilter,
        PermissoesService,
        toasty,
        Departamento,
        MapaService,
        FileUploader,
        ngFileReader) {


       /**
        * Obtem a lista de Permissões
        *
        * @method getPermissoes
		*        
        *
        */   
        PermissoesService.getPermissoes().then(function (perms) {
            $scope.permissoesVisualizacao = perms.permissoesVisualizacao;
            $scope.permissoesCriacao = perms.permissoesCriacao;
            $scope.permissoesEdicao = perms.permissoesEdicao;
            $scope.permissoesRemocao = perms.permissoesRemocao;
            $scope.permissoesExtras = perms.permissoesExtras;
        });


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

        //Apenas para criação de rotas.
       /**
        * Verifica se há novos pontos na rota
        *
        * @method watch
        
        * @param newVal {String} novo valor 
        * @param oldVal {String} valor antigo
        *
        */        
        $scope.$watch('RotasUnificadasManager.rotaAtiva.pontos', function (newArray, oldArray) {

            angular.forEach(newArray, function (ponto) {

                if (ponto.endereco && ponto.endereco.geometry) {
                    ponto.latLng.lat = ponto.endereco.geometry.location.lat();
                    ponto.latLng.lng = ponto.endereco.geometry.location.lng();
                    ponto.endereco = ponto.endereco.formatted_address;
                    atualizarMapa();
                    return;
                }
            });

        }, true);

        /**
         * Formulário com as informações da rota
         *
         * @property formRota
         * @type Object
         */
        $scope.formRota = {};
        
        /**
        * Verifica se o nome da rota foi alterado
        *
        * @method watch
        * @param newVal {String} novo valor 
        * @param oldVal {String} valor antigo
        *
        */           
        $scope.$watch('RotasUnificadasManager.rotaAtiva.nome', function (newVal, oldVal) {
            if (newVal && newVal.length > 0) {
                if ($scope.formRota.nome) {
                    $scope.formRota.nome.error.required = false;
                    $scope.formRota.nome.touch = false;
                }
            }
        });

        /**
         * Lista de agências
         *
         * @property agencias
         * @type Array
         */
        $scope.agencias = [];
        
         /**
        * Obtem a lista de agências
        *
        * @method getAgencias
        *
        */       
        Departamento.getAgencias()
            .then(function (agencias) {
                $scope.agencias = agencias;
            });


       /**
        * Desabilita o endereço
        *
        * @method desabilitarEndereco
        *
        */   
        $scope.desabilitarEndereco = function (ponto) {
            if (RotasUnificadasManager.rotaAtiva == null || (RotasUnificadasManager.rotaAtiva.rotaUnificadaId == null && RotasUnificadasManager.rotaAtiva.kml == null)) {
                return false;
            } else {
                if (RotasUnificadasManager.rotaAtiva.kml) {
                    return true;
                }
                else if ((RotasUnificadasManager.rotaAtiva != null && RotasUnificadasManager.rotaAtiva.pontos[0].latLng.lat == ponto.latLng.lat && RotasUnificadasManager.rotaAtiva.pontos[0].latLng.lng == ponto.latLng.lng)
                    || (RotasUnificadasManager.rotaAtiva != null && RotasUnificadasManager.rotaAtiva.pontos[RotasUnificadasManager.rotaAtiva.pontos.length - 1].latLng.lat == ponto.latLng.lat && RotasUnificadasManager.rotaAtiva.pontos[RotasUnificadasManager.rotaAtiva.pontos.length - 1].latLng.lng == ponto.latLng.lng)) {
                    return true;
                } else {
                    return false;
                }
            }
        }

       /**
        * Desabilita campos da rota alternativa
        *
        * @method desabilitarCamposRotaAlternativa
        *
        */   
        $scope.desabilitarCamposRotaAlternativa = function () {
            if (RotasUnificadasManager.rotaAtiva == null || RotasUnificadasManager.rotaAtiva.rotaUnificadaId == null) {
                return false;
            } else {
                return true;
            }
        }

       /**
        * Atualiza o mapa
        *
        * @method atualizarMapa
        *
        */  
        function atualizarMapa() {

            var rotasAtivas = MapaService.obterRotaUnificadaAtiva();

            _.each(rotasAtivas, function (rotaAtiva) {
                rotaAtiva.setWaypoints(RotasUnificadasManager.rotaAtiva.pontos);
            });
        }

        /**
        * Abre o mosaico de câmeras
        *
        * @method abrirCamerasMosaico
        * @param cameras {String} Json com as informações das cameras que serão exibidas
		*
        */
        function abrirCamerasMosaico(cameras) {
            cameras = cameras.filter(function (camera) {
                return camera.numero > 0;
            });

            if (cameras.length <= 0) {
                return;
            }

            var url = $state.href('mosaico', {
                cameras: JSON.stringify(cameras)
            }, {
                absolute: true
            });

            window.open(url, 'Mosaico', 'menubar=no,location=no,resizable=no,scrollbars=no,status=yes,width=1024,height=600');
        }

       /**
        * Voa para o incidente
        *
        * @method voarParaIncidente
        * @param incidente {String} Identificação do Incidente 
		*
        */
        $scope.voarParaIncidente = function (incidente) {
            CamadasService.reloadIncidentes(true);
            MapaManager.voarParaObjeto(incidente);
            //MapaManager.naoPiscar();
        }

		/**
        * Voa para a camera
        *
        * @method voarParaCamera
        * @param camera {String} Identificação da camera 
		*
        */
        $scope.voarParaCamera = function (camera) {
            CamadasService.ativarMenuDaCamera(camera);
            MapaManager.voarParaObjeto(camera);
            //MapaManager.naoPiscar();
        }
        
        $scope.abrirCamerasMosaico = abrirCamerasMosaico;

		/**
        * Exibe mensagem de acesso não permitido
        *
        * @method exibirMensagemAcessoNaoPermitido
        * 
		*
        */
        function exibirMensagemAcessoNaoPermitido() {
            $mdDialog
                .show($mdDialog.alert()
                    .title($scope.res('COMUM_AVISO'))
                    .content($scope.res('PERMISSAO_AREAATUACAO_VERIFICACAO'))
                    .ok($scope.res('COMUM_OK')));
            return;
        }

		/**
        * Valida a rota a ser salva
        *
        * @method validarSalvarRota
        * @param waypoints {Object} Pontos da Rota (Lat, Lng)
		*
        */
        function validarSalvarRota(waypoints) {
            var filtroPermissao = {};
            filtroPermissao.objeto = "CRIAR_ROTA";
            filtroPermissao.latitude = waypoints[0].de.lat;
            filtroPermissao.longitude = waypoints[0].de.lng;

            PermissoesService.verificarPermissaoAreaAtuacao(filtroPermissao)
                .then(function (resultDe) {
                    if (resultDe) {

                        filtroPermissao.latitude = waypoints[0].para.lat;
                        filtroPermissao.longitude = waypoints[0].para.lng;

                        PermissoesService.verificarPermissaoAreaAtuacao(filtroPermissao)
                            .then(function (resultPara) {
                                if (resultPara) {
                                    confirmarSalvarRota(waypoints);
                                }
                                else {
                                    exibirMensagemAcessoNaoPermitido();
                                    $scope.enableButton = true;
                                }
                            });
                    }
                    else {
                        exibirMensagemAcessoNaoPermitido();
                        $scope.enableButton = true;
                    }
                });
        }

        $scope.enableButton = true;
        
	   /**
        * Salva a rota
        *
        * @method salvarRotaUnificada
        * 
		*
        */        
        $scope.salvarRotaUnificada = function () {

            if ($scope.enableButton == false) {
                return;
            }

            $scope.enableButton = false;

            if (!RotasUnificadasManager.rotaAtiva.hasOwnProperty('nome') || RotasUnificadasManager.rotaAtiva.nome.length === 0) {
                $scope.formRota = {
                    nome: {
                        touched: true,
                        error: {
                            required: true
                        }
                    }
                };

                $scope.enableButton = true;
                return false;
            }
            if (!RotasUnificadasManager.rotaAtiva.hasOwnProperty('DepartamentoId') || RotasUnificadasManager.rotaAtiva.DepartamentoId.length === 0) {
                $scope.formRota = {
                    DepartamentoId: {
                        touched: true,
                        error: {
                            required: true
                        }
                    }
                };

                $scope.enableButton = true;
                return false;
            }

            var waypoints = [];
            _.reduce(RotasUnificadasManager.rotaAtiva.pontos, function (a, sum) {
                waypoints.push({
                    de: a.latLng ? a.latLng : L.latLng(a.lat, a.lng),
                    para: sum.latLng ? sum.latLng : L.latLng(sum.lat, sum.lng)
                });
                return sum;
            });

            validarSalvarRota(waypoints);
        };

   	  /**
        * Informa se a rota foi salva com sucesso
        *
        * @method confirmarSalvarRota
        * @param waypoints {Object} Pontos da Rota (Lat, Lng)
		*
        */  
        function confirmarSalvarRota(waypoints) {
            if (!RotasUnificadasManager.rotaAtiva.id) {
                RotasUnificadasService
                    .salvarRotaUnificada(
                        {
                            nome: RotasUnificadasManager.rotaAtiva.nome,
                            descricao: RotasUnificadasManager.rotaAtiva.descricao,
                            publico: true,
                            trechos: waypoints,
                            DepartamentoId: RotasUnificadasManager.rotaAtiva.DepartamentoId
                                || user.Departamento.id,
                            rotaUnificadaId: RotasUnificadasManager.rotaAtiva.rotaUnificadaId,
                            editavel: !RotasUnificadasManager.rotaAtiva.kml,
                            trajeto: RotasUnificadasManager.rotaAtiva.trajeto,
                            rota: RotasUnificadasManager.rotaAtiva.rota
                        })
                    .then(
                        function (obj) {

                            $scope.enableButton = true;

                            MapaService.removerRotasUnificadasDoMapa();

                            RotasUnificadasManager.rotaAtiva = undefined;
                            RotasUnificadasManager.fechar();

                            $mdDialog.show($mdDialog.alert().title(
                                $scope.res('COMUM_SUCESSO')).content(
                                    $scope.res('MSG_ROTA_CRIADA_SUCESSO'))
                                .ok($scope.res('COMUM_OK')));
                            var rotas = MainState.getDirective('rotas');
                            if (rotas) {
                                rotas.atualizarRotas();
                            }
                        },
                        function (err) {
                            toasty({
                                msg: $scope.res('MSG_ERRO_ROTA_SALVAR')
                            });
                        });

            } else {

                RotasUnificadasService
                    .updateRotaUnificada(
                        {
                            id: RotasUnificadasManager.rotaAtiva.id,
                            nome: RotasUnificadasManager.rotaAtiva.nome,
                            descricao: RotasUnificadasManager.rotaAtiva.descricao,
                            publico: true,
                            trechos: waypoints,
                            DepartamentoId: RotasUnificadasManager.rotaAtiva.DepartamentoId
                                || user.Departamento.id,
                            editavel: !RotasUnificadasManager.rotaAtiva.kml,
                            trajeto: RotasUnificadasManager.rotaAtiva.trajeto,
                            rota: RotasUnificadasManager.rotaAtiva.rota
                        }).then(
                            function (obj) {

                                $scope.enableButton = true;
                                RotasUnificadasManager.fechar();
                                $mdDialog.show($mdDialog.alert().title(
                                    $scope.res('COMUM_SUCESSO')).content(
                                        $scope.res('MSG_ROTA_ATUALIZADA'))
                                    .ok($scope.res('COMUM_OK')));
                                var rotas = MainState.getDirective('rotas');
                                if (rotas) {
                                    rotas.atualizarRotas();
                                }
                            },
                            function (err) {
                                toasty({
                                    msg: $scope.res('MSG_ERRO_ROTA_ATUALIZACAO')
                                });
                            });
            }
        }
        
        /**
        * Fecha a rota
        *
        * @method closeRota
        * 
        * 
        */
        $scope.closeRota = function () {
            $mdDialog.hide();
        };

        /**
        * Voa para o incidente
        *
        * @method selecionarIncidente
        * @param incidente {Object} Identificação do Incidente
        * 
        */
        $scope.selecionarIncidente = function (incidente) {
            CamadasService.reloadIncidentes(true);
            DetalhamentoManager.voarParaObjeto(incidente);
        }

        /**
        * Edita a rota
        *
        * @method selecionarRota
        * @param rota {Object} Identificação da Rota
        * 
        */
        $scope.selecionarRota = function (rota) {
            RotasUnificadasManager.editar(rota);
        }


        /**
        * Voa para a camera
        *
        * @method selecionarCamera
        * @param camera {Object} Identificação da camera
        * 
        */
        $scope.selecionarCamera = function (camera) {
            CamadasService.ativarMenuDaCamera(camera);
            DetalhamentoManager.voarParaObjeto(camera);
        }

        var uploaderKml = $scope.uploaderKml = new FileUploader();

        $scope.inputKml = $('.uploadArquivoKml');

        /**
        * Filtra o arquivos no upload para não permitir arquivos muito grandes 
        *
        * @method filters
        * 
        * 
        */
        $scope.uploaderKml.filters.push({
            'name': 'checkIsFileKML',
            'fn': function (item, evt) {
                var extn = item.name.split(".").pop();

                if (extn !== 'kml' && extn !== 'kmz' && extn !== 'zip') {
                    $mdDialog
                        .show($mdDialog.alert()
                            .title('Formato de arquivo não permitido')
                            .content('O arquivo enviado não é um kml, kmz ou zip válido.')
                            .ok('OK'));

                    return false;
                } else {
                    return true;
                }
            }
        });

        /**
        * Inicia o objeto para o upload 
        *
        * @method abrirUploadKml
        * 
        * 
        */
        $scope.abrirUploadKml = function () {
            $('#admin-rotas-btn-upload').click();
            //$scope.inputKml.click();
        }

        /**
        * Executa alguma instrução durante o processo de upload
        *
        * @method onProgressItem
        * 
        * 
        */
        $scope.uploaderKml.onProgressItem = function (fileItem, progress) {
            console.info('onProgressItem', fileItem, progress);
        };

        $scope.uploaderKml.removeAfterUpload = true;

        /**
        * Procura por uma extensão
        *
        * @method ext
        * 
        * 
        */
        function ext(filename) {
            var index = _.lastIndexOf(filename, '.');
            return filename.substring(index, filename.length);
        }

        /**
        * Listener para inclusão de arquivo
        *
        * @method ngFileReader
        * 
        * 
        */
        ngFileReader.on('fileSelectedROTAS', onFileSelected);

        /**
        * Método chamado após o arquivo ser anexado
        *
        * @method onFileSelected_
        * @param file {Object} arquivo anexado
        * 
        */
        function onFileSelected_(file) {
            var json = KMLParser.loadKML(file.contents, ['Point', 'LineString']);

            var rows = [];

            var geojsonIndex = json.head.indexOf('geojson');
            var nameIndex = json.head.indexOf('name');
            var descriptionIndex = json.head.indexOf('description');

            rows = rows.concat(_.map(json.body, function (row) {

                var poiGeometrico;
                var geojson = JSON.parse(row[geojsonIndex]);

                if (geojson.type !== 'Point') {
                    var feature = {
                        type: 'Feature',
                        geometry: geojson
                    };

                    RotasUnificadasManager.rotaAtiva.rota = [];

                    _.each(geojson.coordinates, function (coordinate) {
                        var latlng = {
                            lat: coordinate[1],
                            lng: coordinate[0]
                        };
                        RotasUnificadasManager.rotaAtiva.rota.push(latlng);
                    })

                    var simplified = turf.simplify(feature, 0.001);
                    var geojson = simplified.geometry;

                    poiGeometrico = new Terraformer.MultiPolygon([geojson.coordinates]);

                    return {

                        nome: row[nameIndex],
                        descricao: row[descriptionIndex],
                        poiGeometrico: poiGeometrico,
                        type: geojson.type,
                        coordinates: geojson.coordinates,
                        tipo: 'LineString'
                    };

                } else {

                    var coordinates = JSON.parse(row[geojsonIndex]).coordinates;

                    return {
                        nome: row[nameIndex],
                        descricao: row[descriptionIndex],
                        latitude: coordinates[1],
                        longitude: coordinates[0],
                        tipo: 'Point'
                    };
                }
            }));
            var pontos = [];
            angular.forEach(rows, function (row) {
                if (row.tipo == 'Point') {
                    pontos.push(L.latLng(row.latitude, row.longitude));
                }
            });

            RotasUnificadasManager.rotaAtiva.pontos = pontos;

            var trajeto = {};
            angular.forEach(rows, function (row) {
                if (row.tipo == 'LineString') {
                    trajeto.type = "LineString";
                    trajeto.coordinates = row.coordinates;
                }
            });

            MapaService.desenharRotaUnificadaKml(pontos);
            MapaService.desenharTrajetoRotaUnificadaKml(trajeto);

        }

 	  /**
        * Método chamado após o arquivo ser anexado
        *
        * @method onFileSelected
        * @param file {Object} arquivo anexado
        * 
        */
        function onFileSelected(file) {
            var json = KMLParser.loadKML(file.contents, ['Point', 'LineString']);

            var rows = [];

            var geojsonIndex = json.head.indexOf('geojson');
            var nameIndex = json.head.indexOf('name');
            var descriptionIndex = json.head.indexOf('description');


            for (var i in json.body) {
                var poiGeometrico;
                var geojson = JSON.parse(json.body[i][geojsonIndex]);
                var row = {};
                if (geojson.type !== 'Point') {
                    var feature = {
                        type: 'Feature',
                        geometry: geojson
                    };

                    RotasUnificadasManager.rotaAtiva.rota = [];

                    _.each(geojson.coordinates, function (coordinate) {
                        var latlng = {
                            lat: coordinate[1],
                            lng: coordinate[0]
                        };
                        RotasUnificadasManager.rotaAtiva.rota.push(latlng);
                    })

                    var simplified = turf.simplify(feature, 0.001);
                    var geojson = simplified.geometry;

                    poiGeometrico = new Terraformer.MultiPolygon([geojson.coordinates]);

                    row.poiGeometrico = poiGeometrico;
                    row.type = geojson.type;
                    row.coordinates = geojson.coordinates;
                    row.tipo = 'LineString';

                } else {

                    var coordinates = geojson.coordinates;

                    row.latitude = coordinates[1];
                    row.longitude = coordinates[0];
                    row.tipo = 'Point';
                }
                rows.push(row);
            }

            var pontos = [];
            for (var index in rows) {
                if (rows[index].tipo == 'Point') {
                    pontos.push(L.latLng(rows[index].latitude, rows[index].longitude));
                }
            }

            RotasUnificadasManager.rotaAtiva.pontos = pontos;

            var trajeto = {};
            for (var index in rows) {
                if (rows[index].tipo == 'LineString') {
                    trajeto.type = "LineString";
                    trajeto.coordinates = rows[index].coordinates;
                }
            }

            MapaService.desenharRotaUnificadaKml(pontos);
            MapaService.desenharTrajetoRotaUnificadaKml(trajeto);
        }
    }


    function s4cAdicionarRotasUnificadas() {
        return {
            restrict: 'E',
            templateUrl: 'app/directives/adicionar-rotas-unificadas/adicionar-rotas-unificadas.html',
            replace: true,
            controller: adicionarRotasUnificadasCtrl,
            link: function ($scope) {
                $scope.res = $scope.$root.res;
                function converte(index) {
                    return ' ' + String.fromCharCode(65 + index);
                }

                angular.extend($scope, {
                    converte: converte
                });
            }
        };
    }

    /**
     * @ngdoc overview
     * @name s4c.components.rotas
     */
    angular.module('s4c.components.rotas-unificadas', [
        's4c.filters.clockTime'
    ])
        .directive('s4cAdicionarRotasUnificadas', s4cAdicionarRotasUnificadas);

}());