Source: directives/zona-observacao/zona-observacao.js

/**
 * @ngdoc directive
 * @name ZonaObservacao
 * @module s4c.components.ZonaObservacao
 *
 * @description
 * `ZonaObservacao` Controller do módulo de Zona de Observação
 *
 * @example
 *   <s4c-zona-observacao>
 *   </s4c-zona-observacao>
 */
(function () {
    'use strict';

    s4cZonaObservacao.$inject = [
        'MapaManager',
        'CamadasService'
    ]

    function s4cZonaObservacao(MapaManager, CamadasService) {
        return {
            restrict: 'E',
            templateUrl: 'app/directives/zona-observacao/zona-observacao.html',
            replace: true,
            scope: {},
            controller: ZonaObservacaoCtrl,
            link: function ($scope, $elem, $attrs) {

                $scope.sections = {
                    alarmesHidden: true,
                    tarefasHidden: true,
                    poisHidden: true,
                    outrasInformacoesHidden: true
                };

                $scope.voarPara = voarPara;
                $scope.showZoDialog = false;
                $scope.timeStep = 30;
                $scope.inputKml = $elem.find('.uploadArquivoKml');

                /**
                 * @method voarPara
                 * @param {*} obj 
                 * @param {*} tipo 
                 */
                function voarPara(obj, tipo) {

                    if (tipo == 'base') {
                        CamadasService.reloadBasesConhecimento(true);
                    } else if (tipo == 'poi') {
                        CamadasService.ativarMenuPoi(obj)
                    } else if (tipo == 'camera') {
                        CamadasService.ativarMenuDaCamera(obj);
                    } else if (tipo == 'incidente') {
                        CamadasService.ativarMenuDoIncidente(obj);
                    }

                    MapaManager.voarParaObjetoBlue(obj);
                }

            }
        };
    }


    ZonaObservacaoCtrl.$inject = [
        '$scope',
        '$q',
        '$mdDialog',
        'ZonaObservacaoService',
        'TarefaService',
        '$state',
        'CamadasService',
        'MainState',
        'AuthService',
        'MapaService',
        'CommService',
        'DetalhamentoManager',
        'ZonaDeObservacaoManager',
        'BotoesManager',
        'toasty',
        'ZonasDeObservacaoFilter',
        'localize',
        'FileUploader',
        'API_ENDPOINT',
        'PermissoesService'
    ];

    function ZonaObservacaoCtrl($scope,
        $q,
        $mdDialog,
        ZonaObservacaoService,
        TarefaService,
        $state,
        CamadasService,
        MainState,
        AuthService,
        MapaService,
        CommService,
        DetalhamentoManager,
        ZonaDeObservacaoManager,
        BotoesManager,
        toasty,
        ZonasDeObservacaoFilter,
        localize,
        FileUploader,
        API_ENDPOINT,
        PermissoesService) {

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

        PermissoesService.getPermissoes().then(function (perms) {
            $scope.permissoesVisualizacao = perms.permissoesVisualizacao;
            $scope.permissoesCriacao = perms.permissoesCriacao;
            $scope.permissoesEdicao = perms.permissoesEdicao;
            $scope.permissoesRemocao = perms.permissoesRemocao;
        });


        $scope.minTimeTermino = '00:00';
        $scope.maxTimeInicio = '00:00';

        $scope.$watch('ZO.inicio', function (newValue, oldValue) {
            if (!newValue) {
                return;
            }

            if ((!$scope.ZO.fim && $scope.ZO.id != null) || ($scope.ZO.fim && $scope.ZO.id == null)) {
                var inicio = $scope.ZO.inicio;
                var fim = moment(inicio).endOf('day');
                $scope.ZO.fim = fim.format('MM/DD/YYYY HH:mm');
            }

            $scope.minTimeTermino = ($scope.ZO.inicio) ? (newValue == $scope.ZO.fim ? $scope.ZO.inicio : false) : false;
            $scope.maxTimeInicio = ($scope.ZO.fim) ? (newValue == $scope.ZO.fim ? $scope.ZO.fim : false) : false;
        });

        $scope.$watch('ZO.fim', function (newValue, oldValue) {
            $scope.minTimeTermino = ($scope.ZO.inicio) ? (newValue == $scope.ZO.inicio ? $scope.ZO.inicio : false) : false;
            $scope.maxTimeInicio = ($scope.ZO.fim) ? (newValue == $scope.ZO.inicio ? $scope.ZO.fim : false) : false;
        });

        $scope.GruposUsuarios = [];
        $scope.Usuarios = [];

        var kmls = {};

        $scope.$botoes = BotoesManager;
        $scope.botoesItems = [{
            title: 'Twitter',
            icon: '/assets/images/Incidentes/ic_social_twitter_color_24px.svg',
            action: function () {

                var lat = $scope.ZO.geojson.geometry.coordinates[1];
                var long = $scope.ZO.geojson.geometry.coordinates[0];

                var info = { latitude: lat, longitude: long };

                $scope.$botoes.abrirTwitter(info);
            }
        }, {
            title: $scope.res('MAIN_MENU_MENSAGERIA'),
            icon: '/assets/images/Incidentes/ic_social_telegram_color_24px.svg',
            action: function () {
                $scope.ZO.tipoObjeto = 'zonaObservacao';
                $scope.$botoes.abrirMensageria(true, $scope.ZO, 'zona_observacao');
            }
        }];

        $scope.openShare = false;

        $scope.openOptionShare = function () {
            $scope.openShare = !$scope.openShare;
        };

        $scope.deleteTxt = false;
        $scope.areaType;
        $scope.enablePoly = true;

        /**
         * @method desenharArea
         * @param {*} areaType
         * @param {*} $event
         */
        $scope.desenharArea = function (areaType, $event) {

            if ($scope.deleteTxt == false) {
                $scope.deleteTxt = true;
            }

            $scope.removerArea(areaType, $event);

            if (ZonaDeObservacaoManager && ZonaDeObservacaoManager.drawInstance) {
                ZonaDeObservacaoManager.drawInstance.disable();
            }

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

            $scope.enablePoly = false;

            $scope.areaType = areaType;

            var ZonaDeObservacaoManager = MainState.getManager('ZonaDeObservacaoManager'),
                el = $event.currentTarget;

            angular.element('.desenhar-area-content-zona_observacao a').removeClass('active');
            el.className = 'active';

            MapaService.dataminingViewport();

            MapaService.draw(areaType).then(function (instances) {
                ZonaDeObservacaoManager.drawInstance = instances[0];
                ZonaDeObservacaoManager.drawInstance.enable();
            });

        };

        /**
         * @method removerArea
         * @param {*} areaType
         * @param {*} $event
         */
        $scope.removerArea = function (areaType, $event) {

            $mdDialog.hide();
            $scope.deleteTxt = false;
            $scope.enablePoly = true;
            var ZonaDeObservacaoManager = MainState.getManager('ZonaDeObservacaoManager'),
                el = $event.currentTarget;

            MapaService.removerDesenho();
        };

        CommService.on('tarefas:update', function (tarefa) {
            var tarefaAntiga = _.find($scope.ZO.tarefas, {
                id: tarefa.id
            });

            if (tarefaAntiga) {
                _.updateValues(tarefaAntiga, tarefa);
            }

            updateZonaColor();

            $scope.$apply();
        });

        var instance = ZonasDeObservacaoFilter.getInstance('zonas-de-observacao-filter');

        /**
         * @method atualizandoInformacoes
         */
        function atualizarInformacoes() {
            $scope.atualizandoInformacoes = true;
            var zonaGeojson = $scope.ZO.geojson;
            var promiseArray = [];

            promiseArray.push(ZonaObservacaoService
                .pegarCenso(zonaGeojson.geometry)
                .then(function (data) {
                    $scope.ZO.censo = {
                        populacao: data.populacao,
                        criancas: data.criancas,
                        domicilios: data.domicilios,
                        idosos: data.idosos
                    };
                }));

            promiseArray.push(ZonaObservacaoService
                .pegarTwitter(zonaGeojson)
                .then(function (data) {
                    var bounds = ZonaDeObservacaoManager.bounds;
                    var bbox = turf.bboxPolygon([
                        bounds.bottomRight.lat,
                        bounds.bottomRight.lng,
                        bounds.topLeft.lat,
                        bounds.topLeft.lng
                    ]);
                    var statuses = _.filter(data.statuses, function (status) {
                        if (!status.geo) {
                            return false;
                        }
                        var ponto = turf.point(status.geo.coordinates);
                        var inside = turf.inside(ponto, bbox);
                        return inside;
                    });
                    $scope.ZO.tweets = statuses;
                    ZonaDeObservacaoManager.mostrarTweets(statuses);
                }));

            promiseArray.push(ZonaObservacaoService
                .pegarBasesConhecimento(zonaGeojson)
                .then(function (data) {
                    $scope.ZO.bases = data;
                }));

            promiseArray.push(ZonaObservacaoService
                .pegarIncidentes(zonaGeojson)
                .then(function (data) {
                    $scope.ZO.incidentes = data;
                }));

            promiseArray.push(ZonaObservacaoService
                .pegarCameras(zonaGeojson)
                .then(function (data) {
                    $scope.ZO.cameras = data;
                }));

            promiseArray.push(ZonaObservacaoService
                .pegarPoisArea(zonaGeojson)
                .then(function (data) {

                    $scope.ZO.pois = [];

                    _.each(Object.keys(data), function (key) {
                        $scope.ZO.pois.push({
                            nome: data[key].nome,
                            categorias: _.map(Object.keys(data[key].cat), function (catKey) {
                                return {
                                    nome: data[key].cat[catKey].nome,
                                    categoria: data[key].cat[catKey].cat,
                                    pois: data[key].cat[catKey].pois
                                }
                            })
                        });

                        acervos[acervo] = dados;
                    });
                }));

            calcularMultidao();

            $q.all(promiseArray)
                .then(function () {
                    $scope.atualizandoInformacoes = false;
                    $scope.sections = {
                        alarmesHidden: false,
                        tarefasHidden: false,
                        poisHidden: false,
                        outrasInformacoesHidden: false
                    };
                });
        }

        /**
         * @method calcularMultidao
         */
        function calcularMultidao() {
            //var obj = ZonaDeObservacaoManager.area;
            var zonaGeojson = $scope.ZO.geojson;

            if (zonaGeojson == null || zonaGeojson == undefined) {
                return;
            }

            if ($scope.ZO.densidade == undefined || $scope.ZO.densidade == null) {
                $scope.ZO.densidade = "6";
            }

            $scope.multidaoLoading = true;

            ZonaObservacaoService
                .pegarMultidao(zonaGeojson.geometry, $scope.ZO.densidade)
                .then(function (data) {
                    if (data.ERRO) {
                        $scope.multidaoErro = true;
                        $scope.multidaoLoading = false;
                        return;
                    } else {
                        $scope.multidaoErro = false;
                        $scope.multidaoLoading = false;

                        $scope.ZO.multidao = parseInt(data.multidao, 10);
                        $scope.ZO.areaSelecionada = data.area;
                    }
                }, function (err) {
                    $scope.multidaoLoading = false;
                });
        }

        /**
         * @method voarParaTweet
         * @param {*} tweet 
         */
        function voarParaTweet(tweet) {
            var MapaManager = MainState.getManager('MapaManager');
            MapaManager.voarParaTweet(tweet);
        }

        /**
         * @method deletarZona
         * @param {*} evt 
         */
        function deletarZona(evt) {

            var removerZOMsg = localize.getLocalizedString('ZONAOBSERVACAO_MENSAGEMREMOVER');
            var sim = localize.getLocalizedString('COMUM_SIM');
            var nao = localize.getLocalizedString('COMUM_NAO');

            $mdDialog.show({
                targetEvent: evt,
                scope: $scope.$new(),
                template: '<md-dialog>' +
                    '  <md-content>' + removerZOMsg + '</md-content>' +
                    '  <div class="md-actions">' +
                    '    <md-button ng-click="deleteConfirm()">' + sim + '</md-button>' +
                    '    <md-button ng-click="deleteCancel()">' + nao + '</md-button>' +
                    '  </div>' +
                    '</md-dialog>'
            });

        }

        /**
         * @method deleteDesenhoModal
         * @param {*} evt 
         */
        function deleteDesenhoModal(evt) {

            $mdDialog.show({
                targetEvent: evt,
                scope: $scope.$new(),
                template: '<md-dialog>' +
                    '  <md-content>' + $scope.res('CANCELAR_DESENHO') + '</md-content>' +
                    '  <div class="md-actions">' +
                    '    <md-button ng-click="removerArea(areaType, $event)">' + $scope.res('COMUM_SIM') + '</md-button>' +
                    '    <md-button ng-click="cancelDesenho()">' + $scope.res('COMUM_NAO') + '</md-button>' +
                    '  </div>' +
                    '</md-dialog>'
            });

        }

        /**
         * @method cancelDesenho
         */
        function cancelDesenho() {
            $mdDialog.hide();
            $scope.deleteTxt = false;
        }

        /**
         * @method deleteCancel
         */
        function deleteCancel() {
            $mdDialog.hide();
        }

        /**
         * @method deleteConfirm
         */
        function deleteConfirm() {
            $mdDialog.hide();
            ZonaObservacaoService
                .deletarZona($scope.ZO.id)
                .then(function () {
                    CamadasService.reloadZonasObservacao();
                    ZonaDeObservacaoManager.fechar();
                    // instance.trigger('reloadZonaObs');
                });
        }

        /**
         * @method carregarZona
         * @param {*} zona 
         */
        function carregarZona(zona) {
            mostrarLista();

            ZonaObservacaoService
                .pegarZona(zona.id)
                .then(function (data) {

                    var topLeft = JSON.parse(data.topLeft);
                    var bottomRight = JSON.parse(data.bottomRight);

                    $scope
                        .$parent
                        .ZonaDeObservacaoManager
                        .abrirExistente({
                            topLeft: {
                                lat: topLeft.coordinates[1],
                                lng: topLeft.coordinates[0]
                            },
                            bottomRight: {
                                lat: bottomRight.coordinates[1],
                                lng: bottomRight.coordinates[0]
                            }
                        }, zona);
                });
        }

        /**
         * @method mostrarLista
         */
        function mostrarLista() {
            if ($scope.modo === 'visualizacao') {

                $scope.modo = 'lista';

                ZonaObservacaoService
                    .pegarZonas()
                    .then(function (data) {
                        $scope.zonas = data;
                    });

            } else {
                $scope.modo = 'visualizacao';
            }
        }

        /**
         * @method isParticipante
         * @param {*} zona 
         */
        function isParticipante(zona) {
            var zonaPublica = isPublic(zona);
            var retorno = false; //Foi feito assim para evitar o bug do javascript de não sair do método quando tem um return dentro de um foreach que está danetro de um if 
            if (zonaPublica) {
                retorno = true;
            }

            if (!zona.criador) {
                return true;
            }

            if (zona.criador.id == $scope.me.id) {
                retorno = true;
            }
            if (zona.Usuarios != null) {
                _.each(zona.Usuarios, function (usuario) {
                    if (usuario.id == $scope.me.id) {
                        retorno = true;
                    }
                });
            }
            if (zona.GruposUsuarios != null) {
                _.each(zona.GruposUsuarios, function (grupo) {
                    _.each(grupo.Usuarios, function (usuario) {
                        if (usuario.id == $scope.me.id) {
                            retorno = true;
                        }
                    });
                });
            }
            return retorno;
        }

        /**
         * @method isPublic
         * @param {*} zona 
         */
        function isPublic(zona) {
            if ((zona.Usuarios == null || zona.Usuarios.length == 0) && (zona.GruposUsuarios == null || zona.GruposUsuarios.length == 0)) {
                return true;
            } else {
                return false;
            }
        }

        /**
         * @method buscarDados
         * @param {*} zona 
         */
        function buscarDados(zona) {
            var deferred = $q.defer();

            if (typeof zona.geojson !== 'object') {
                zona.geojson = JSON.parse(zona.geojson);
            }

            $scope.multidaoErro = false;
            $scope.multidaoLoading = false;

            zona.inicio = parseInt(zona.inicio, 10);
            zona.fim = parseInt(zona.fim, 10);

            if (zona.id) {
                $scope.ZO = zona || {
                    id: null,
                    multidao: {
                        erro: false
                    }
                };
            } else {
                $scope.ZO.latitude = zona.latitude;
                $scope.ZO.longitude = zona.longitude;
            }

            $scope.ZO.canEditParticipants = isParticipante($scope.ZO);

            $scope.ZO.geojson = zona.geojson;

            $scope.ZO.tarefas = [];

            var promiseArray = [];

            if ($scope.ZO.id) {
                promiseArray.push(ZonaObservacaoService.pegarTarefas(zona)
                    .then(function (tarefas) {
                        $scope.ZO.tarefas = tarefas;
                        updateZonaColor();
                    }));

                promiseArray.push(ZonaObservacaoService.pegarAlarmes(zona.id)
                    .then(function (alarmes) {
                        $scope.ZO.alarmes = _.orderBy(alarmes, function (a) {
                            return a.nome.toLowerCase();
                        });
                    }));
            }

            promiseArray.push(ZonaObservacaoService
                .pegarCenso(zona.geojson.geometry)
                .then(function (data) {
                    $scope.ZO.censo = {
                        populacao: data.populacao,
                        criancas: data.criancas,
                        domicilios: data.domicilios,
                        idosos: data.idosos
                    };
                }));

            promiseArray.push(ZonaObservacaoService
                .pegarTwitter(zona.geojson.properties.bounds)
                .then(function (data) {
                    var statuses = _.filter(data.statuses, function (status) {
                        if (!status.geo) {
                            return false;
                        }

                        // Cloning Array
                        var coords = status.geo.coordinates.slice();
                        var ponto = turf.point(coords.reverse());

                        var geom = _.clone(zona.geojson);

                        // Buffer area if it's a Circle
                        if (zona.geojson.geometry.type === 'Circle') {
                            var geojson = turf.point(zona.geojson.geometry.coordinates);
                            geom = turf.buffer(geojson, zona.geojson.geometry.radius / 1000, 'kilometers').features[0];
                        }

                        var inside = turf.inside(ponto, geom);
                        return inside;
                    });
                    $scope.ZO.tweets = statuses;
                    ZonaDeObservacaoManager.mostrarTweets(statuses);
                }));

            promiseArray.push(ZonaObservacaoService
                .pegarBasesConhecimento(zona.geojson.geometry)
                .then(function (data) {
                    $scope.ZO.bases = data;
                }));

            promiseArray.push(ZonaObservacaoService
                .pegarIncidentes(zona.geojson.geometry)
                .then(function (data) {
                    $scope.ZO.incidentes = data;
                }));

            promiseArray.push(ZonaObservacaoService
                .pegarCameras(zona.geojson.geometry)
                .then(function (data) {
                    $scope.ZO.cameras = data;
                }));

            promiseArray.push(ZonaObservacaoService
                .pegarPoisArea(zona.geojson.geometry)
                .then(function (data) {

                    $scope.ZO.pois = [];

                    var nomeAcervos = _.chain(data)
                        .map('acervoNome')
                        .uniq()
                        .value();

                    _.each(nomeAcervos, function (nome, index) {
                        if (nome == null) {
                            nomeAcervos[index] = 'Pois';
                        }
                    });

                    var acervos = {};

                    _.each(nomeAcervos, function (acervo) {
                        acervos[acervo] = [];
                    });

                    _.each(Object.keys(acervos), function (acervo) {

                        var dados = _.filter(data, function (poi) {
                            return (poi.acervoNome === acervo || acervo == 'Pois');
                        });

                        acervos[acervo] = dados;
                    });

                    _.each(Object.keys(acervos), function (acervoKey) {
                        // Lista de categorias deste acervo:
                        var nomeCategorias = _.chain(acervos[acervoKey])
                            .map('categoriaNome')
                            .uniq()
                            .value();

                        var acervoCategorias = {};

                        _.each(nomeCategorias, function (categoria) {
                            acervoCategorias[categoria] = _.filter(acervos[acervoKey], function (dados) {
                                return dados.categoriaNome === categoria;
                            });
                        });

                        acervos[acervoKey] = acervoCategorias;
                    });

                    $scope.ZO.pois = acervos;

                }));

            calcularMultidao();

            $q.all(promiseArray)
                .then(function () {
                    $scope.atualizandoInformacoes = false;
                    $scope.sections = {
                        alarmesHidden: false,
                        tarefasHidden: false,
                        poisHidden: false,
                        outrasInformacoesHidden: false
                    };
                    deferred.resolve();
                }, function () {
                    deferred.reject();
                });


            $scope.GruposUsuarios = $scope.ZO.GruposUsuarios || $scope.GruposUsuarios || [];
            $scope.Usuarios = $scope.ZO.Usuarios || $scope.Usuarios || [];

            popularKmls();
        }

        var message;

        /**
         * @method validateDateZO
         * @param {*} ZO 
         */
        function validateDateZO(ZO) {
            var isValid = true;
            var inicioZO = moment(ZO.inicio, 'DD/MM/YYYY HH:mm');
            var fimZO = moment(ZO.fim, 'DD/MM/YYYY HH:mm');

            if (!ZO.id) {
                if (inicioZO.isBefore(moment(), 'day')) {
                    message = localize.getLocalizedString('ZONAOBSERVACAO_MENSAGEMDATAERROMENOR');
                    isValid = false;
                    return isValid;;
                }
            }

            if (inicioZO.isAfter(fimZO)) {
                message = localize.getLocalizedString('ZONAOBSERVACAO_MENSAGEMDATAMENOR');
                isValid = false;
            }

            return isValid;
        }

        $scope.saving = false;

        /**
         * @method showSaveDialog
         * @param {*} $event 
         */
        function showSaveDialog($event) {

            $scope.saving = true;
            var mensagemExtra = '';

            // Área não desenhada
            if (_.isEmpty(ZonaDeObservacaoManager.area)) {
                var confirm = $mdDialog.confirm()
                    .title(localize.getLocalizedString('COMUM_AVISO'))
                    .content(localize.getLocalizedString('ZONAOBSERVACAO_MENSAGEMAREA'))
                    .ariaLabel(localize.getLocalizedString('ZONAOBSERVACAO_SEMDESENHO'))
                    .ok(localize.getLocalizedString('COMUM_OK'));

                $mdDialog.show(confirm);
                $scope.saving = false;
            } else {

                if (_.isEmpty($scope.ZO.nome) || _.isEmpty($scope.ZO.descricao)) {
                    var confirm = $mdDialog.confirm()
                        .title(localize.getLocalizedString('COMUM_AVISO'))
                        .content(localize.getLocalizedString('ZONAOBSERVACAO_MENSAGEMNOMEDESCRICAO'))
                        .ariaLabel(localize.getLocalizedString('ZONAOBSERVACAO_MENSAGEMNOMEDESCRICAO'))
                        .ok(localize.getLocalizedString('COMUM_OK'));

                    $mdDialog.show(confirm);

                    $scope.formZonaObservacao.nome.$touched = true;
                    $scope.formZonaObservacao.descricao.$touched = true;
                    $scope.saving = false;
                } else {

                    if (!$scope.formZonaObservacao.$valid) {
                        $scope.saving = false;
                        return;
                    }

                    if ($scope.ZO.id == null && !validateDateZO($scope.ZO)) {
                        $mdDialog
                            .show($mdDialog.alert()
                                .title(localize.getLocalizedString('COMUM_AVISO'))
                                .content(message)
                                .ok(localize.getLocalizedString('COMUM_OK')));

                        $scope.saving = false;
                        return false;
                    }

                    $scope.ZO.GruposUsuarios = $scope.GruposUsuarios || [];
                    $scope.ZO.Usuarios = $scope.Usuarios || [];

                    var filtroPermissao = {};
                    filtroPermissao.objeto = "CRIAR_ZONA_OBSERVACAO";
                    var zonaGeojson = $scope.ZO.geojson;
                    filtroPermissao.geoJson = JSON.stringify(zonaGeojson.geometry);

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

                                if (!ZonaDeObservacaoManager.data.id) {

                                    /* Se o dia for o atual e o horário for anterior ao atual,
                                     * setar horário escolhido para o horário atual.
                                     */
                                    var dataInicio = moment($scope.ZO.inicio, 'DD/MM/YYYY HH:mm');
                                    if (dataInicio.isSame(moment(), 'day') && dataInicio.isBefore(moment(), 'minute')) {
                                        $scope.ZO.inicio = moment().format('DD/MM/YYYY HH:mm');

                                        mensagemExtra += '\r\n Atenção: horário de inicio alterado para o horário atual.';
                                    }

                                    ZonaDeObservacaoManager
                                        .salvar($scope.ZO)
                                        .then(function (data) {

                                            $scope.saving = false;
                                            uploadArquivos(data);
                                            //instance.trigger('reloadZonaObs');
                                            $mdDialog
                                                .show($mdDialog.alert()
                                                    .title(localize.getLocalizedString('COMUM_SUCESSO'))
                                                    .content(localize.getLocalizedString('ZONAOBSERVACAO_TITULO') + localize.getLocalizedString('COMUM_MENSAGEM_SALVACOMSUCESSO') + mensagemExtra)
                                                    .ok(localize.getLocalizedString('COMUM_OK')));

                                            $scope.removerArea($scope.areaType, $event);

                                            setTimeout(function () {
                                                CamadasService.exibirZonasDeObservacao();
                                                DetalhamentoManager.abrirZonaDeObservacao(data.id);
                                                popularKmls();
                                            }, 500);
                                        }, function (err) {
                                            $scope.saving = false;
                                            $mdDialog
                                                .show($mdDialog.alert()
                                                    .title(localize.getLocalizedString('COMUM_ERRO'))
                                                    .content($scope.res(err.data.message))
                                                    .ok(localize.getLocalizedString('COMUM_OK')));
                                        });
                                } else {
                                    ZonaObservacaoService
                                        .atualizarZO(ZonaDeObservacaoManager.data.id, $scope.ZO)
                                        .then(function (data) {

                                            $scope.saving = false;
                                            uploadArquivos(data.data);

                                            $mdDialog
                                                .show($mdDialog.alert()
                                                    .title(localize.getLocalizedString('COMUM_SUCESSO'))
                                                    .content(localize.getLocalizedString('ZONAOBSERVACAO_TITULO') + localize.getLocalizedString('COMUM_MENSAGEM_SALVACOMSUCESSO') + mensagemExtra)
                                                    .ok(localize.getLocalizedString('COMUM_OK')));
                                            setTimeout(function () {
                                                DetalhamentoManager.abrirZonaDeObservacao($scope.ZO.id);
                                                popularKmls();
                                            }, 1000);

                                        }, function (err) {
                                            $scope.saving = false;
                                            $mdDialog
                                                .show($mdDialog.alert()
                                                    .title(localize.getLocalizedString('COMUM_ERRO'))
                                                    .content(err.message)
                                                    .ok(localize.getLocalizedString('COMUM_OK')));
                                        });

                                }
                            }
                            else {
                                $mdDialog
                                    .show($mdDialog.alert()
                                        .title($scope.res('COMUM_AVISO'))
                                        .content($scope.res('PERMISSAO_AREAATUACAO_VERIFICACAO'))
                                        .ok($scope.res('COMUM_OK')));
                                $scope.saving = false;
                                return;
                            }
                        });
                }
            }
        }

        /**
         * @method abrirCamerasMosaico
         * @param {*} cameras 
         */
        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');
        }

        /**
         * @method fecharZO
         */
        function fecharZO() {
            $scope.sections = {
                alarmesHidden: true,
                tarefasHidden: true,
                poisHidden: true,
                outrasInformacoesHidden: true
            };

            $scope.kmls = [];
            uploaderKml.queue = [];
            $scope.openShare = false;
            $scope.ZO = {};
            ZonaDeObservacaoManager.fechar();
        }

        /**
         * @method updateZonaColor
         */
        function updateZonaColor() {
            var flagNaoConcluida = false;

            _.each($scope.ZO.tarefas, function (tarefa) {
                if (!tarefa.concluida) {
                    flagNaoConcluida = true;
                }
            });

            if (!flagNaoConcluida && $scope.ZO.tarefas && $scope.ZO.tarefas.length > 0) {
                ZonaDeObservacaoManager.area.setStyle({
                    fillColor: '#00ff00'
                });
            } else if (flagNaoConcluida && $scope.ZO.tarefas.length > 0) {
                ZonaDeObservacaoManager.area.setStyle({
                    fillColor: '#ff0000'
                });
            } else {
                ZonaDeObservacaoManager.area.setStyle({
                    fillColor: '#eeff00'
                });
            }
        }

        /**
         * @instance alarmeOptions
         */
        var alarmeOptions = {
            tipos: [{
                label: $scope.res('MSI_NOME'),
                value: 'IncidenteZO'
            }, {
                label: 'Twitter',
                value: 'TwitterZO'
            }, {
                label: $scope.res('ALARM_OPTION_TEMPO'),
                value: 'TempoZO'
            }, {
                label: $scope.res('CERCA_VIRTUAL_ENTRADA'),
                value: 'CercaVirtualEntradaZO'
            }, {
                label: $scope.res('CERCA_VIRTUAL_SAIDA'),
                value: 'CercaVirtualSaidaZO'
            }, {
                label: $scope.res('CERCA_VIRTUAL_PERMANENCIA'),
                value: 'CercaVirtualPermanenciaZO'
            }, {
                label: $scope.res('COMUM_ATIVAR_CAMADA'),
                value: 'AtivarCamadaZO'
            }],
            opcoesTempo: [{
                nome: '1 ' + $scope.res('COMUM_MINUTO'),
                valor: '1 minutes'
            }, {
                nome: '5 ' + $scope.res('COMUM_MINUTOS'),
                valor: '5 minutes'
            }, {
                nome: '30 ' + $scope.res('COMUM_MINUTOS'),
                valor: '30 minutes'
            }, {
                nome: '1 ' + $scope.res('COMUM_HORA'),
                valor: '1 hours'
            }, {
                nome: '2 ' + $scope.res('COMUM_HORAS'),
                valor: '2 hours'
            }, {
                nome: '6 ' + $scope.res('COMUM_HORAS'),
                valor: '6 hours'
            }, {
                nome: '12 ' + $scope.res('COMUM_HORAS'),
                valor: '12 hours'
            }, {
                nome: '2 ' + $scope.res('COMUM_DIAS'),
                valor: '2 days'
            }, {
                nome: '3 ' + $scope.res('COMUM_DIAS'),
                valor: '3 days'
            }, {
                nome: '5 ' + $scope.res('COMUM_DIAS'),
                valor: '5 days'
            }, {
                nome: '7 ' + $scope.res('COMUM_DIAS'),
                valor: '7 days'
            }],
            labelTipos: {
                'categoria': 'categoria',
                'poi': 'ponto de interesse',
                'viaturaV1': 'viatura - v1',
                'viaturaV2': 'viatura - v2',
            },
            tipoItens: [
                {
                    value: 'poi',
                    label: 'Ponto de Interesse'
                }, {
                    value: 'viaturaV1',
                    label: 'Viatura (v1)'
                }, {
                    value: 'viaturaV2',
                    label: 'Viatura (v2)'
                }
            ]
        };

        /**
         * @method adicionarRange
         * 
         * @param {*} alarme 
         * @param {*} zonaObservacao 
         * @param {*} range 
         */
        function adicionarRange(alarme, zonaObservacao, range) {
            $mdDialog.show({
                templateUrl: 'app/directives/zona-observacao/dialog-range.html',
                locals: {
                    alarme: alarme,
                    zonaObservacao: zonaObservacao,
                    range: range
                },
                controller: ['$scope', '$mdDialog', 'alarme', 'zonaObservacao', '$log', 'range', adicionarRangeCtrl]
            });
        }

        /**
         * 
         * Controller da funcionalidade de adicionar um novo range para o alarme
         * 
         * @method adicionarRangeCtrl
         * 
         * @param {*} $scope 
         * @param {*} $mdDialog 
         * @param {*} alarme 
         * @param {*} zonaObservacao 
         * @param {*} $log 
         * @param {*} range 
         */
        function adicionarRangeCtrl($scope, $mdDialog, alarme, zonaObservacao, $log, range) {
            $scope.res = $scope.$root.res;

            var rangeOptions = {
                min: _formatDate(zonaObservacao.inicio),
                max: _formatDate(zonaObservacao.fim)
            };

            $scope.alarme = alarme;
            if (!$scope.alarme.detalhes) {
                $scope.alarme.detalhes = {};
            }

            var ranges = $scope.alarme.detalhes.ranges || [];
            $scope.range = range || {};
            $scope.editIndex = ranges.indexOf(range);

            function _formatDate(date) {
                if (!date || date === '') return;
                return moment(date, 'DD/MM/YYYY HH:mm').format();
            }

            function _formatDateReverse(date) {
                if (!date || date === '') return;
                return moment(date).format('DD/MM/YYYY HH:mm');
            }

            function _addRange(range) {
                ranges.push(range);
                return ranges;
            }

            function _replaceRange(range) {
                ranges[$scope.editIndex] = range;
                return ranges;
            }

            function _getRange() {
                return {
                    start: _formatDate($scope.range.start),
                    end: _formatDate($scope.range.end)
                };
            }

            if ($scope.range.start) {
                $scope.range.start = _formatDateReverse(range.start);
            }

            if ($scope.range.end) {
                $scope.range.end = _formatDateReverse(range.end);
            }

            function _hasEqualRange(singleRange) {
                $scope.error = 'Já existe um range para estas datas.';
            }

            function _validateRange(range) {
                var rangeStart = (range.start && range.start !== '') ? moment(range.start) : false;
                var rangeEnd = (range.end && range.end !== '') ? moment(range.end) : false;

                if (!rangeStart && !rangeEnd) {
                    $scope.error = 'Você não selecionou nenhuma data.';
                    return false;
                }

                if (rangeStart) {
                    if (!(rangeStart.isSame(rangeOptions.min) || rangeStart.isAfter(rangeOptions.min))) {
                        $scope.error = 'As datas selecionadas estão fora do range da zona de observação';
                        return false;
                    }

                    if (rangeStart.isSame(rangeOptions.max) || rangeStart.isAfter(rangeOptions.max)) {
                        $scope.error = 'As datas selecionadas estão fora do range da zona de observação';
                        return false;
                    }
                }

                if (rangeEnd) {
                    if (!(rangeEnd.isSame(rangeOptions.max) || rangeEnd.isBefore(rangeOptions.max))) {
                        $scope.error = 'As datas selecionadas estão fora do range da zona de observação';
                        return false;
                    }

                    if (rangeEnd.isSame(rangeOptions.min) || rangeEnd.isBefore(rangeOptions.min)) {
                        $scope.error = 'As datas selecionadas estão fora do range da zona de observação';
                        return false;
                    }
                }

                if (rangeStart && rangeEnd) {
                    if (rangeEnd.isBefore(rangeStart)) {
                        $scope.error = 'A data inicial não pode ser maior que a data final.';
                        return false;
                    }
                }

                return true;
            };

            function _tratarAlarme(alarme) {
                if (alarme.detalhes.ranges) {
                    alarme.detalhes.ranges = alarme.detalhes.ranges.map(function (range) {
                        if (range.start) {
                            range.start = _formatDate(range.start);
                        }

                        if (range.end) {
                            range.end = _formatDate(range.end);
                        }

                        return range;
                    });
                }
            }

            $scope.cancelar = function (alarme) {
                $mdDialog.cancel();
                _tratarAlarme(alarme);
                adicionarAlarme(alarme);
            };

            $scope.salvar = function () {
                var range = _getRange();

                if (_validateRange(range)) {
                    $scope.alarme.detalhes.ranges = ($scope.editIndex === -1) ? _addRange(range) : _replaceRange(range);
                    $mdDialog.hide();
                    //_tratarAlarme(alarme);
                    adicionarAlarme(alarme);
                }

            };
        }

        /**
         * 
         * @method adicionarAlarme
         * 
         * @param {*} alarme 
         * @param {*} alarmeRange 
         */
        function adicionarAlarme(alarme, alarmeRange) {
            var zonaObservacao = $scope.ZO;

            $mdDialog.show({
                templateUrl: 'app/directives/zona-observacao/dialog-alarme.html',
                locals: {
                    alarme: alarme,
                    ZO: zonaObservacao,
                    alarmeRange: alarmeRange
                },
                controller: ['$scope', '$mdDialog', 'alarme', 'Categoria', 'Poi', 'Viatura', '$q', 'Acervo', 'Grupo', '$rootScope',
                    function ($scope, $mdDialog, alarme, Categoria, Poi, Viatura, $q, Acervo, Grupo, $rootScope) {
                        $scope.res = $rootScope.res;

                        var index = lunr(function () {
                            this.field('chave_estrangeira');
                            this.field('nome');
                            this.field('descricao');
                            this.ref('_id');
                        }),
                            indexedItens = {};


                        $scope.tipos = [{
                            label: 'Incidente',
                            value: 'IncidenteZO'
                        }, {
                            label: 'Twitter',
                            value: 'TwitterZO'
                        }, {
                            label: 'Tempo',
                            value: 'TempoZO'
                        }, {
                            label: 'Cerca Virtual (Entrada)',
                            value: 'CercaVirtualEntradaZO'
                        }, {
                            label: 'Cerca Virtual (Saída)',
                            value: 'CercaVirtualSaidaZO'
                        }, {
                            label: 'Cerca Virtual (Permanência)',
                            value: 'CercaVirtualPermanenciaZO'
                        }, {
                            label: 'Ativar camada',
                            value: 'AtivarCamadaZO'
                        }];

                        $scope.opcoesTempo = [{
                            nome: '1 minuto',
                            valor: '1 minutes'
                        }, {
                            nome: '5 minutos',
                            valor: '5 minutes'
                        }, {
                            nome: '30 minutos',
                            valor: '30 minutes'
                        }, {
                            nome: '1 hora',
                            valor: '1 hours'
                        }, {
                            nome: '2 horas',
                            valor: '2 hours'
                        }, {
                            nome: '6 horas',
                            valor: '6 hours'
                        }, {
                            nome: '12 horas',
                            valor: '12 hours'
                        }, {
                            nome: '2 dias',
                            valor: '2 days'
                        }, {
                            nome: '3 dias',
                            valor: '3 days'
                        }, {
                            nome: '5 dias',
                            valor: '5 days'
                        }, {
                            nome: '7 dias',
                            valor: '7 days'
                        }];

                        $scope.ZO = zonaObservacao;
                        $scope.tipos = alarmeOptions.tipos;
                        $scope.opcoesTempo = alarmeOptions.opcoesTempo;
                        $scope.labelTipos = alarmeOptions.labelTipos;
                        $scope.tipoItens = alarmeOptions.tipoItens;

                        $scope.autocomplete = {
                            queryDetalhesAlarme: '',
                            detalhesAlarme: {}
                        };

                        $scope.exibirFormChaveEstrangeira = false;
                        $scope.alarme = alarme;
                        if (!$scope.alarme) {
                            $scope.alarme = {
                                detalhes: {}
                            };
                        }
                        var rangeOptions = {
                            min: _formatDate(zonaObservacao.inicio),
                            max: _formatDate(zonaObservacao.fim)
                        };



                        var rangesAlarme = $scope.alarme.detalhes.rangesAlarme || [];
                        $scope.alarmeRange = alarmeRange || {};
                        $scope.editIndex = rangesAlarme.indexOf(alarmeRange);

                        function _formatDate(date) {
                            if (!date || date === '') return;
                            return moment(date, 'DD/MM HH:mm').format();
                        }

                        function _formatDateReverse(date) {
                            if (!date || date === '') return;
                            return moment(date).format('DD/MM HH:mm');
                        }

                        function _addRange(alarmeRange) {
                            rangesAlarme.push(alarmeRange);
                            return rangesAlarme;
                        }

                        function _replaceRange(alarmeRange) {
                            rangesAlarme[$scope.editIndex] = alarmeRange;
                            return rangesAlarme;
                        }

                        function _getRange() {
                            return {
                                start: _formatDate($scope.alarmeRange.start),
                                end: _formatDate($scope.alarmeRange.end)
                            };

                        }

                        if ($scope.alarmeRange.start) {
                            $scope.alarmeRange.start = _formatDateReverse(alarmeRange.start);
                        }

                        if ($scope.alarmeRange.end) {
                            $scope.alarmeRange.end = _formatDateReverse(alarmeRange.end);
                        }

                        function _setGrupos(grupos) {
                            return _.map(grupos, function (grupo) {
                                return {
                                    id: grupo.id,
                                    nome: grupo.nome
                                }
                            });
                        }

                        function _setAcervos(acervos, grupoId) {
                            if (grupoId) {
                                return _.filter(acervos, function (acervo) {
                                    if (acervo.GrupoId == grupoId)
                                        return {
                                            id: acervo.id,
                                            nome: acervo.nome
                                        }
                                });
                            }
                            else {
                                return _.map(acervos, function (acervo) {
                                    return {
                                        id: acervo.id,
                                        nome: acervo.nome
                                    }
                                });
                            }
                        }

                        function _setCategorias(categorias, acervoId) {
                            if (acervoId) {
                                return _.filter(categorias, function (categoria) {
                                    if (categoria.AcervoId == acervoId) {
                                        categoria.tipo = 'categoria';
                                        categoria._id = _.uniqueId();
                                        indexedItens[categoria._id] = categoria;
                                        index.add(categoria);
                                        return categoria;
                                    }
                                });
                            }
                            else {
                                return _.map(categorias, function (categoria) {
                                    categoria.tipo = 'categoria';
                                    categoria._id = _.uniqueId();
                                    indexedItens[categoria._id] = categoria;
                                    index.add(categoria);
                                    return categoria;
                                });
                            }
                        }

                        $scope.adicionarRange = adicionarRange;

                        $scope.removeRange = function (alarmeRange) {
                            var rangesAlarme = $scope.alarme.detalhes.ranges;
                            rangesAlarme = rangesAlarme.splice(rangesAlarme.indexOf(alarmeRange), 1);
                        };

                        Grupo.query().$promise.then(function (grupos) {
                            $scope.alarme.detalhes.grupoId = null;
                            $scope.alarme.detalhes.acervoId = null;
                            $scope.grupos = _setGrupos(grupos);

                        })

                        $scope.getSetAcervos = function (grupoId) {
                            $scope.alarme.detalhes.acervoId = null;
                            $scope.alarme.detalhes.categoriaId = null;
                            Acervo.query().$promise.then(function (acervos) {
                                $scope.acervos = _setAcervos(acervos, grupoId);
                            });
                        }

                        $scope.getSetCategorias = function (acervoId) {
                            $scope.alarme.detalhes.categoriaId = null;
                            $scope.alarme.detalhes.subCategoriaId1 = null;
                            $scope.categorias = _setCategorias($scope.todasCategorias, acervoId);
                        }

                        $scope.subCategorias = [];

                        $scope.getSetSubCategorias = function (categoriaId, nivel) {
                            $scope.alarme.detalhes.categoriaId = categoriaId;
                            $scope.totalDeNiveis = 4; //quantidade de selects para as subcategorias + 1
                            if (nivel == 0) {
                                $scope.alarme.detalhes['subCategoriaId' + nivel] = null;
                                for (var i = nivel; i < $scope.totalDeNiveis + 1; i++) {
                                    $scope.alarme.detalhes['subCategoriaId' + (nivel + 1)] = null;
                                }
                            }
                            else {
                                for (var i = nivel; i < $scope.totalDeNiveis + 1; i++) {
                                    $scope.alarme.detalhes['subCategoriaId' + (nivel + 1)] = null;
                                }
                            }
                            $scope.subCategorias[nivel] = _.filter($scope.todasCategorias, function (categoria) {
                                return categoria.CategoriumId == categoriaId;
                            });
                            $scope.subCategorias[nivel] = _.map($scope.subCategorias[nivel], function (categoria) {
                                return {
                                    id: categoria.id,
                                    nome: categoria.nome,
                                    CategoriumId: categoria.CategoriumId
                                }
                            })
                        }

                        Categoria.query().$promise.then(function (categorias) {
                            $scope.todasCategorias = angular.copy(categorias);
                            $scope.categorias = _setCategorias(categorias);

                            if ($scope.alarme && $scope.alarme.id) {
                                if ($scope.alarme.tipo == 'CercaVirtualPermanenciaZO') {
                                    var horaInicio = $scope.alarme.detalhes.horaInicio.hour + ':' +
                                        $scope.alarme.detalhes.horaInicio.minute;

                                    var horaFim = $scope.alarme.detalhes.horaFim.hour + ':' +
                                        $scope.alarme.detalhes.horaFim.minute;

                                    $scope.alarme.detalhes.horaInicio = horaInicio;
                                    $scope.alarme.detalhes.horaFim = horaFim;
                                }

                                if ($scope.alarme.tipo.indexOf('CercaVirtual') > -1) {
                                    $scope.dontTriggerAutoComplete = true;
                                    $scope.autocomplete.queryDetalhesAlarme = $scope.alarme.detalhes.chave_estrangeira ||
                                        _.find($scope.categorias, {
                                            tipo: 'categoria',
                                            id: $scope.alarme.detalhes.categoriaId
                                        }).nome
                                }
                            }
                        });

                        $scope.filtrarItensDetalheAlarme = function () {

                            if ($scope.dontTriggerAutoComplete) {
                                $scope.dontTriggerAutoComplete = false;
                                return [];
                            }

                            if ($scope.autocomplete.queryDetalhesAlarme) {
                                return $q.all([
                                    Poi.pesquisar($scope.autocomplete.queryDetalhesAlarme),
                                    Viatura.pesquisar($scope.autocomplete.queryDetalhesAlarme, 1),
                                    Viatura.pesquisar($scope.autocomplete.queryDetalhesAlarme, 2),
                                ]).then(function (results) {
                                    var pois = _.map(results[0], function (poi) {
                                        poi.tipo = 'poi';
                                        return poi;
                                    });

                                    var viaturasV1 = _.map(results[1], function (poi) {
                                        poi.tipo = 'viaturaV1';
                                        return poi;
                                    });
                                    var viaturasV2 = _.map(results[2], function (poi) {
                                        poi.tipo = 'viaturaV2';
                                        return poi;
                                    });

                                    var categorias = _.map(index.search($scope.autocomplete.queryDetalhesAlarme),
                                        function (match) {
                                            return indexedItens[match.ref];
                                        });

                                    return _.chain(pois)
                                        .concat(viaturasV1)
                                        .concat(viaturasV2)
                                        .concat(categorias)
                                        .concat([{
                                            tipo: 'viaturaV2',
                                            nome: 'Todas',
                                            _isOptionAll: true
                                        }, {
                                            tipo: 'viaturaV1',
                                            nome: 'Todas',
                                            _isOptionAll: true
                                        }])
                                        .orderBy('nome')
                                        .value();
                                })
                            }
                        }

                        $scope.selecionarItemDetalhesAlarme = function () {
                            if ($scope.autocomplete.detalhesAlarme) {
                                if ($scope.autocomplete.detalhesAlarme.tipo == 'categoria') {
                                    $scope.alarme.detalhes.categoriaId = $scope.autocomplete.detalhesAlarme.id;
                                    delete $scope.alarme.detalhes.chave_estrangeira;
                                    $scope.alarme.detalhes.tipoItem = 'poi';
                                } else {

                                    if (!$scope.autocomplete.detalhesAlarme._isOptionAll) {
                                        $scope.alarme.detalhes.chave_estrangeira =
                                            $scope.autocomplete.detalhesAlarme.chave_estrangeira;
                                        delete $scope.alarme.detalhes.categoriaId;
                                    }

                                    $scope.alarme.detalhes.tipoItem = $scope.autocomplete.detalhesAlarme.tipo;
                                }

                                $scope.dontTriggerAutoComplete = true;
                                $scope.autocomplete.queryDetalhesAlarme = ($scope.autocomplete.detalhesAlarme.nome ||
                                    $scope.autocomplete.detalhesAlarme.chave_estrangeira);

                            } else {
                                delete $scope.alarme.detalhes.categoriaId;
                                delete $scope.alarme.detalhes.chave_estrangeira;
                            }
                        };

                        $scope.digitarChaveEstrangeira = function () {
                            $scope.tentouEnviar = false;
                            $scope.exibirFormChaveEstrangeira = true;
                        };

                        $scope.selecionarItem = function () {
                            $scope.tentouEnviar = false;
                            $scope.exibirFormChaveEstrangeira = false;
                        };

                        $scope.limparForm = function () {
                            $scope.tentouEnviar = false;
                            $scope.exibirFormChaveEstrangeira = false;
                        };

                        function _tratarAlarme(alarme) {
                            if (alarme.tipo == 'CercaVirtualPermanenciaZO') {
                                var horaInicio = {
                                    hour: alarme.detalhes.horaInicio.split(':')[0],
                                    minute: alarme.detalhes.horaInicio.split(':')[1],
                                };

                                var horaFim = {
                                    hour: alarme.detalhes.horaFim.split(':')[0],
                                    minute: alarme.detalhes.horaFim.split(':')[1],
                                };

                                alarme.detalhes.horaInicio = horaInicio;
                                alarme.detalhes.horaFim = horaFim;
                            };
                        }

                        function _validarDataRange(alarmeRange) {

                            var rangeStart = (alarmeRange.start && alarmeRange.start !== '') ? moment(alarmeRange.start) : false;
                            var rangeEnd = (alarmeRange.end && alarmeRange.end !== '') ? moment(alarmeRange.end) : false;

                            if (rangeStart) {
                                if (!(rangeStart.isSame(rangeOptions.min) || rangeStart.isAfter(rangeOptions.min))) {
                                    $scope.error = 'As datas selecionadas estão fora do range da zona de observação';
                                    return false;
                                }

                                if (rangeStart.isSame(rangeOptions.max) || rangeStart.isAfter(rangeOptions.max)) {
                                    $scope.error = 'As datas selecionadas estão fora do range da zona de observação';
                                    return false;
                                }
                            }

                            if (rangeEnd) {
                                if (!(rangeEnd.isSame(rangeOptions.max) || rangeEnd.isBefore(rangeOptions.max))) {
                                    $scope.error = 'As datas selecionadas estão fora do range da zona de observação';
                                    return false;
                                }

                                if (rangeEnd.isSame(rangeOptions.min) || rangeEnd.isBefore(rangeOptions.min)) {
                                    $scope.error = 'As datas selecionadas estão fora do range da zona de observação';
                                    return false;
                                }
                            }

                            if (rangeStart && rangeEnd) {
                                if (rangeEnd.isBefore(rangeStart)) {
                                    $scope.error = 'A data inicial não pode ser maior que a data final.';
                                    return false;
                                }
                            }

                            return true;
                        };

                        function _existemAlarmesIguais(alarme) {
                            var alarmes = $scope.ZO.alarmes;

                            var exists = alarmes.filter(function (alarmeExistente) {

                                var _hasEqualStart = false;
                                var _hasEqualEnd = false;
                                var _hasSameType = false;
                                var _hasSameName = false;

                                // Se o alarme for ele mesmo, ele está sendo editado, pulamos.
                                if (alarme.id === alarmeExistente.id) return;

                                //if (alarme.nome === alarmeExistente.nome) return true;
                                if (alarme.tipo === alarmeExistente.tipo) _hasSameType = true;
                                if (alarme.nome === alarmeExistente.nome) _hasSameName = true;

                                if (alarme.detalhes.start && alarmeExistente.detalhes.start) {
                                    if (moment(alarme.detalhes.start, 'DD/MM/YYYY HH:mm').isSame(
                                        moment(alarmeExistente.detalhes.start, 'DD/MM/YYYY HH:mm')
                                    )) _hasEqualStart = true;
                                }

                                if (alarme.detalhes.end && alarmeExistente.detalhes.end) {
                                    if (moment(alarme.detalhes.end, 'DD/MM/YYYY HH:mm').isSame(
                                        moment(alarmeExistente.detalhes.end, 'DD/MM/YYYY HH:mm')
                                    )) _hasEqualEnd = true;
                                }

                                if (alarme.tipo === 'TempoZO') {
                                    _hasEqualEnd = true;
                                }

                                return ((_hasSameType && _hasEqualEnd && _hasEqualStart) || (_hasSameType && _hasSameName));

                            });

                            return !!exists.length;
                        }

                        function _validar(alarme) {
                            if (_existemAlarmesIguais(alarme)) {
                                return {
                                    valido: false,
                                    message: 'Já existe um alarme com os mesmos dados.'
                                };
                            }

                            if (alarme.tipo.indexOf('CercaVirtual') > -1) {
                                if (alarme.tipo == 'CercaVirtualPermanenciaZO') {
                                    return {
                                        valido: alarme.detalhes.tipoItem && (alarme.detalhes.horaInicio && alarme.detalhes.horaFim)
                                    };
                                } else {
                                    return {
                                        valido: alarme.detalhes.tipoItem
                                    }
                                }
                            }

                            if (alarme.tipo == 'AtivarCamadaZO') {
                                if (!alarme.detalhes.categoriaId) {
                                    return {
                                        valido: false,
                                        message: 'Você precisa selecionar pelo menos um grupo, um acervo e uma categoria.'
                                    };
                                }
                            }

                            return {
                                valido: true
                            };
                        }

                        $scope.cancelar = function (alarme) {
                            _tratarAlarme(alarme);
                            $mdDialog.cancel();
                        };

                        $scope.salvar = function (alarme) {
                            $scope.tentouEnviar = true;
                            var alarmeRange = _getRange();
                            if (_validarDataRange(alarmeRange)) {
                                $scope.alarme.detalhes.rangesAlarme = ($scope.editIndex === -1) ? _addRange(alarmeRange) : _replaceRange(alarmeRange);

                                if ($scope.zonaObservacao.$valid) {
                                    var validacao = _validar(alarme);
                                    if (validacao.valido) {
                                        _tratarAlarme(alarme);
                                        $mdDialog.hide(alarme);
                                    }
                                }
                                else {
                                    if (validacao.message) {
                                        toasty({
                                            msg: validacao.message
                                        });
                                    }
                                }
                            }
                        };
                    }
                ]
            }).then(function (alarme) {

                if (alarme.id) {
                    ZonaObservacaoService.updateAlarme(alarme).then(listarAlarmes)
                } else {
                    ZonaObservacaoService.addAlarme($scope.ZO.id, alarme).then(listarAlarmes)
                }
            });
        }

        /**
         * @method removerAlarme
         * @param {*} alarme 
         */
        function removerAlarme(alarme) {
            ZonaObservacaoService.removerAlarme(alarme.id)
                .then(function () {
                    ZonaObservacaoService.pegarAlarmes($scope.ZO.id)
                        .then(function (alarmes) {
                            $scope.ZO.alarmes = alarmes;
                        });
                }, function (err) {
                    $mdDialog
                        .show($mdDialog.alert()
                            .title(localize.getLocalizedString('COMUM_ERRO'))
                            .content(err.data.message)
                            .ok(localize.getLocalizedString('COMUM_OK')));
                })
        }

        /**
         * @method listarAlarmes
         */
        function listarAlarmes() {
            ZonaObservacaoService.pegarAlarmes($scope.ZO.id)
                .then(function (alarmes) {
                    $scope.ZO.alarmes = alarmes;
                })
        }

        /**
         * @method tarefaZOConcluir
         * @param {*} tarefaZO 
         */
        function tarefaZOConcluir(tarefaZO) {
            if (tarefaZO.nome.length > 0) {
                $mdDialog.hide(tarefaZO);
            } else {
                $mdDialog
                    .show($mdDialog.alert()
                        .title($scope.res('COMUM_ATENCAO'))
                        .content($scope.res('MENSAGEM_ERRO_TITULO_VAZIO'))
                        .ok($scope.res('COMUM_OK')));
            }
        }

        /**
         * @method salvarTarefaZO
         */
        function salvarTarefaZO() {
            var usuarios = $scope.usuarios;
            $mdDialog.show({
                templateUrl: 'app/directives/zona-observacao/tarefa.html',
                controller: function ($scope, $mdDialog, $rootScope) {
                    $scope.res = $rootScope.res;
                    $scope.usuarios = usuarios;
                    $scope.tarefaZO = {
                        nome: '',
                        titulo: '',
                        descricao: ''
                    };
                    $scope.tarefaZOConcluir = tarefaZOConcluir;
                }
            }).then(function (tarefaZO) {
                tarefaZO.dataInicio = Date.now();
                tarefaZO.ZonaObservacaoId = $scope.ZO.id;
                ZonaObservacaoService.addTarefa($scope.ZO.id, tarefaZO)
                    .then(function (data) {
                        $scope.ZO.tarefas = data;

                        updateZonaColor();

                        $mdDialog
                            .show($mdDialog.alert()
                                .title($scope.res('COMUM_SUCESSO'))
                                .content($scope.res('MENSAGEM_SUCESSO_ADICAO_TAREFA'))
                                .ok($scope.res('COMUM_OK')));
                    });
            });
        }

        /**
         * @method atualizarTarefa
         * @param {*} tarefa 
         */
        function atualizarTarefa(tarefa) {

            var t = _.clone(tarefa);
            t.concluida = !t.concluida;

            if (tarefa.concluida) {
                tarefa.dataFim = Date.now();
            } else {
                tarefa.dataFim = null;
            }
            tarefa.concluida = !tarefa.concluida;

            ZonaObservacaoService.updateTarefa(tarefa.id, t)
                .then(function (data) {
                    var flagNaoConcluida = false;
                    _.each($scope.ZO.tarefas, function (tarefa) {
                        if (!tarefa.concluida) {
                            flagNaoConcluida = true;
                        }
                    });

                    if (!flagNaoConcluida && $scope.ZO.tarefas.length > 0) {

                        ZonaDeObservacaoManager.area.setStyle({
                            fillColor: '#00ff00'
                        });

                    } else if (flagNaoConcluida && $scope.ZO.tarefas.length > 0) {

                        ZonaDeObservacaoManager.area.setStyle({
                            fillColor: '#ff0000'
                        });

                    } else {
                        ZonaDeObservacaoManager.area.setStyle({
                            fillColor: '#eeff00'
                        });
                    }
                });
        }

        /**
         * @method removerTarefa
         * @param {*} tarefa 
         */
        function removerTarefa(tarefa) {
            ZonaObservacaoService
                .removerTarefa(tarefa.id)
                .then(function (data) {

                    var index = _.findIndex($scope.ZO.tarefas, {
                        id: tarefa.id
                    });

                    if (index >= 0) {
                        $scope.ZO.tarefas.splice(index, 1);
                    }

                    var flagNaoConcluida = false;
                    _.each($scope.ZO.tarefas, function (tarefa) {
                        if (!tarefa.concluida) {
                            flagNaoConcluida = true;
                        }
                    });

                    if (!flagNaoConcluida && $scope.ZO.tarefas.length > 0) {

                        ZonaDeObservacaoManager.area.setStyle({
                            fillColor: '#00ff00'
                        });

                    } else if (flagNaoConcluida && $scope.ZO.tarefas.length > 0) {

                        ZonaDeObservacaoManager.area.setStyle({
                            fillColor: '#ff0000'
                        });

                    } else {
                        ZonaDeObservacaoManager.area.setStyle({
                            fillColor: '#eeff00'
                        });
                    }
                });
        }

        TarefaService.getUsuarios()
            .then(function (usuarios) {
                $scope.usuarios = _.map(usuarios, function (usuario) {
                    return {
                        id: usuario.id,
                        nome: usuario.nome,
                        email: usuario.email //Este campo não é retornado após a chamada ao serviço
                    };
                });
            });

        /**
         * @method zerar
         */
        function zerar() {
            $scope.ZO = {
                multidao: {
                    erro: false
                },
                pois: []
            };

            uploaderKml.queue = [];

            $scope.GruposUsuarios = [];
            $scope.Usuarios = [];

            _.forEach($scope.kmls, function (kml) {
                _.forEach(kml.data, function (camada) {
                    MapaService.removerCamada(kmls[camada.id]);
                });
            });

            $scope.kmls = [];
            kmls = [];
        }

        // Chamado quando a Zona de Observação é fechada
        /**
         * @method onClose
         */
        function onClose() {
            zerar();
        }

        /**
         * @method getTweets
         */
        function getTweets() {
            return $scope.ZO.tweets;
        }

        /**
         * @method excluirArquivo
         * 
         * @param {*} e 
         * @param {*} camada 
         */
        function excluirArquivo(e, camada) {
            var confirm = $mdDialog.confirm()
                .title($scope.res('MSG_DESEJA_EXCLUIR_CAMADA'))
                .ariaLabel($scope.res('MSG_EXCLUIR_CAMADA'))
                .ok($scope.res('COMUM_SIM'))
                .cancel($scope.res('COMUM_NAO'));
            $mdDialog.show(confirm).then(function () {
                ZonaObservacaoService.removerCamada(camada.id);
                $mdDialog
                    .show($mdDialog.alert()
                        .title($scope.res('COMUM_EXCLUIDO'))
                        .content($scope.res('CAMADA_EXCLUIDO_SUCESSO'))
                        .ok($scope.res('COMUM_OK')));

                setTimeout(function () {
                    DetalhamentoManager.abrirZonaDeObservacao($scope.ZO.id);
                    MapaService.removerCamada(kmls[camada.id]);
                }, 1000);

            });
        }


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

        $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;
                }
            }
        });

        /**
         * @method toggleKmlZonaObservacao
         * @param {*} camada 
         */
        function toggleKmlZonaObservacao(camada) {
            if (camada.ativo) {
                ZonaDeObservacaoManager.ativarKml(API_ENDPOINT + 'camadas/' + camada.id + '/kml', camada,
                    function (layer) {
                        kmls[camada.id] = layer;
                    });
            } else {
                MapaService.removerCamada(kmls[camada.id]);
            }
        }

        /**
         * @method popularKmls
         */
        function popularKmls() {
            $scope.kmls = [];

            var resultado = {};

            _.each($scope.ZO.Camadas, function (camada) {
                if (camada.tipo === 'KML' || camada.tipo === 'ZIP') {
                    if (camada.id) {
                        var _d = camada.Departamento;
                        resultado[_d.id] = {
                            id: _d.id,
                            nome: _d.nome,
                            data: []
                        };
                    } else {
                        resultado.novo = {
                            id: null,
                            nome: localize.getLocalizedString('COMUM_NOVOARQUIVO'),
                            data: []
                        };
                    }
                }
            });

            _.each($scope.ZO.Camadas, function (camada) {
                if (camada.tipo === 'KML' || camada.tipo === 'ZIP') {
                    if (camada.id) {
                        resultado[camada.Departamento.id].data.push(camada);
                    } else {
                        resultado.novo.data.push(camada);
                    }
                }
            });

            $scope.kmls = resultado;
        }


        /**
         * @method uploadArquivos
         * @param {*} _zona_observacao 
         */
        function uploadArquivos(_zona_observacao) {
            // upload de arquivos kml
            if (uploaderKml.queue.length > 0) {
                uploaderKml.url = '/zona_observacao/' + _zona_observacao.id + '/kml';
                _.each(uploaderKml.queue, function (file) {
                    var extn = file._file.name.split(".").pop();
                    var tipoFile = 'KML';
                    if (extn == 'zip') {
                        tipoFile = 'ZIP';
                    }
                    file.formData = [{
                        nome: file.novonome,
                        tipo: tipoFile,
                        DepartamentoId: AuthService.user.info.Departamento.id
                    }];
                });
                uploaderKml.uploadAll();
            }
        }

        function abrirUploadKml() {
            $scope.inputKml.click();
        }

        $scope.uploaderKml.onBeforeUploadItem = function (item) {
            item.url = uploaderKml.url;
            var token = window.sessionStorage.getItem('s4cToken');
            var tokenObj = JSON.parse(token);
            item.headers = {
                'Authorization': 'Bearer ' + tokenObj.access_token
            };
        };

        $scope.uploaderKml.onProgressItem = function (fileItem, progress) {
            console.info('onProgressItem', fileItem, progress);
        };

        $scope.uploaderKml.onAfterAddingFile = function (item) {
            $mdDialog.show({
                templateUrl: 'app/directives/zona-observacao/dialog-camada.html',
                controller: function ($scope) {
                    $scope.res = $scope.$root.res;
                    $scope.camada = {};
                    $scope.tipo = 'Arquivo';
                    $scope.rename = function () {
                        item.novonome = $scope.camada.nome;
                        $mdDialog.hide();
                    }
                },
                locals: {}
            }).then(function () { }, function () {
                uploaderKml.removeFromQueue(item);
            });
        };

        $scope.uploaderKml.alias = 'arquivo';
        $scope.uploaderKml.removeAfterUpload = true;

        function ext(filename) {
            var index = _.lastIndexOf(filename, '.');
            return filename.substring(index, filename.length);
        }

        angular.extend($scope, {
            excluirArquivo: excluirArquivo,
            abrirUploadKml: abrirUploadKml,
            removerAlarme: removerAlarme,
            deletarZona: deletarZona,
            deleteDesenhoModal: deleteDesenhoModal,
            deleteConfirm: deleteConfirm,
            deleteCancel: deleteCancel,
            cancelDesenho: cancelDesenho,
            abrirCamerasMosaico: abrirCamerasMosaico,
            carregarZona: carregarZona,
            mostrarLista: mostrarLista,
            salvarTarefaZO: salvarTarefaZO,
            adicionarAlarme: adicionarAlarme,
            showSaveDialog: showSaveDialog,
            atualizarTarefa: atualizarTarefa,
            removerTarefa: removerTarefa,
            atualizarInformacoes: atualizarInformacoes,
            toggleKmlZonaObservacao: toggleKmlZonaObservacao,
            tarefaZOConcluir: tarefaZOConcluir,
            fecharZO: fecharZO,
            calcularMultidao: calcularMultidao,
            voarParaTweet: voarParaTweet,
            multidaoErro: false,
            multidaoLoading: false,
            kmls: [],
            $apiZO: {
                zerar: zerar,
                buscarDados: buscarDados,
                onClose: onClose,
                getTweets: getTweets
            },
            ZO: {
                criadorId: '',
                canEditParticipants: false,
                multidao: {
                    erro: false
                }
            },
            me: AuthService.user.info
        });

        MainState.registerDirective('zonaObservacao', $scope.$apiZO);

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



    /**
     * @ngdoc overview
     * @name s4c.components.zonaObservacao
     */
    angular.module('s4c.components.zonaObservacao', ['angular-toasty', 's4c.components.mapa'])
        .directive('s4cZonaObservacao', s4cZonaObservacao);

})();