Source: directives/camadas/camadas.js

/**
 * @ngdoc directives
 * @name camadas
 * @module s4c.directives.camadas.camadas
 *
 * @description
 * `camadasCtrl` gerencia as camadas do sistema.
 *
 *@example
 *   <s4c-camadas>
 *   </s4c-camadas>
 */
(function () {
    'use strict';

    function s4cCamadas() {
        return {
            restrict: 'E',
            transclude: 'true',
            scope: {},
            controller: camadasCtrl,
            templateUrl: 'app/directives/camadas/camadas.html'
        };
    }

    /**
     * @ngdoc overview
     * @name s4c.components.camadas
     */
    angular.module('s4c.components.camadas', ['ui.tree'])
        .directive('s4cCamadas', s4cCamadas);

    camadasCtrl.$inject = [
        '$scope',
        'CamadasService',
        'PermissoesService',
        'Menu',
        'Preset',
        '$http',
        '$mdDialog',
        'API_ENDPOINT',
        'MapaService',
        'toasty',
        'MainState',
        '$window'];

    function camadasCtrl(
        $scope,
        CamadasService,
        PermissoesService,
        Menu,
        Preset,
        $http,
        $mdDialog,
        API_ENDPOINT,
        MapaService,
        toasty,
        MainState,
        $window) {

        $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.permissoesExtras = perms.permissoesExtras;
        });

        // Auto start the Main Menu of Camadas
        startMainMenu();

       /**
        * Sets the parent on the node  
        *
        * @method _indexNode
		*        
        * @param parent {Object} Menu Pai
        * @param menu {Object} Menu 
		*               
        */ 
        function _indexNode(parent, menu) {
            /* Sets the parent on the node */
            menu.parentNode = parent;

            /* Recursive check for subMenus */
            return _indexMenu(menu);
        }

      /**
        * Faz a indexação dos menus
        *
        * @method _indexMenu
		*        
        * @param menu {Object} Menu 
		*               
        */ 
        function _indexMenu(menu) {
            /* Menu should have subMenus to index */
            if (!menu.hasOwnProperty('subMenus')) {
                return;
            }

            var linkParent = _.partial(_indexNode, menu);

            return _.map(menu.subMenus, linkParent);
        }

        $scope.expanded = false;
        
      /**
        * Expande ou fecha todos os menus
        *
        * @method expandCollapse
		*        
		*               
        */         
        $scope.expandCollapse = function () {
            $scope.expanded = !$scope.expanded;

            if ($scope.expanded) {
                angular.element(document.getElementById("camada-tree")).scope().expandAll();
            } else {
                angular.element(document.getElementById("camada-tree")).scope().collapseAll();
            }
        }

      /**
        * Obtem a lista de menus
        *
        * @method _getMenuList
		*        
        * @param menus {Array} Menu 
		*               
        */ 
        function _getMenuList(menus) {
            return _.chain(menus)
                .map(function (menu) {
                    return _.nodeToArray(menu, 'subMenus');
                })
                .flatten()
                .reject('menuSensor')
                .value();
        }

        /* Get the Main Menu of Camadas */
      /**
        * Get the Main Menu of Camadas 
        *
        * @method startMainMenu
		*        
		*               
        */         
        function startMainMenu() {

            Menu.obter(true)
                .then(function (menus) {
                    var menuList = _getMenuList(menus);
                    CamadasService.menusPorAcervo = _.groupBy(menuList, 'acervoTipoId');
                    CamadasService.grupos = _.each(menus, function (menu) {
                        menu.subMenus = _.sortBy(menu.subMenus, 'texto');
                    });

                    _.map(CamadasService.grupos, _indexMenu);

                    $scope.grupos = CamadasService.grupos;

                    for (var index in $scope.grupos) {
                        $scope.grupos[index].subMenus = _.filter($scope.grupos[index].subMenus, function (subMenu) {
                            return hasPermission(subMenu) && isNotInABlackList(subMenu);
                        });
                    }

                    var _grupos = [];
                    _.each($scope.grupos, function (grupo) {
                        if (grupo.subMenus != null && grupo.subMenus.length > 0) {
                            _grupos.push(grupo);
                        }
                    });

                    $scope.grupos = _grupos.sort(function (a, b) {
                        return a.texto > b.texto ? 1 : a.texto < b.texto ? -1 : 0
                    });

                    _desativarMenus();
                    CamadasService.markCategories(Preset.config.preset.categorias);
                    CamadasService.markMenuCamadas(Preset.config.preset.menuCamadas);
                    CamadasService.isLoaded = true;
                });
        }

      /**
        * Define se é pra exibir os indicadores (usados na coloração do mapa) para o menu
        *
        * @method _getMenuList
		*        
        * @param node {Object} Menu 
		*               
        */ 
        function isToShowColorMapSelector(node) {
            if (CamadasService.indicadores.length > 0 && node.isToShowColorMapSelector) {
                return true;
            } else {
                return false;
            }
        }


      /**
        * Verifica se o meunu pode ou não ser exibido
        *
        * @method isNotInABlackList
		*        
        * @param subMenu {Object} SubMenu 
		*               
        */ 
        function isNotInABlackList(subMenu) {
            if (subMenu.urlSubMenus == 'menuCamada/zona_observacao' && !MainState.isToShow('zona_mapa')) {
                return false;
            }
            if (subMenu.url == 'incidente' && !MainState.isToShow('incidentes_mapa')) {
                return false;
            }
            if (subMenu.url == 'base_conhecimento/geojson' && !MainState.isToShow('base_mapa')) {
                return false;
            }
            if (subMenu.url == 'planejamento/geojson' && !MainState.isToShow('planejamento_mapa')) {
                return false;
            }
            if (subMenu.urlSubMenus == 'menuCamada/camera' && !MainState.isToShow('camera_mapa')) {
                return false;
            }
            if (subMenu.urlSubMenus == 'menuCamada/area_atuacao' && !MainState.isToShow('area_atuacao_mapa')) {
                return false;
            }
            if (subMenu.urlSubMenus == 'menuCamada/viatura' && !MainState.isToShow('viatura_mapa')) {
                return false;
            }
            return true;
        }

      /**
        * Desativa os menus
        *
        * @method _desativarMenus
		*        
		*               
        */ 
        function _desativarMenus() {
            if ($scope.grupos != null && $scope.grupos.length > 0) {
                _.each(CamadasService.grupos, function (grupo) {
                    _.each(grupo.subMenus, function (acervo) {

                        if (acervo.subMenus) {
                            _.each(acervo.subMenus, function (categoria) {
                                if (categoria.ativo) {
                                    categoria.ativo = false;
                                }
                            });
                        }
                    });
                });
            }
        }

      /**
        * Muda o indicador usado na coloração do mapa
        *
        * @method changeMapColor
		*        
        * @param obj {Object} Item da combo 
		*               
        */
        function changeMapColor(obj) {
            //$window.sessionStorage.setItem('INDICADOR_SELECTOR', CamadasService.indicadores[indicador].label);
            $window.sessionStorage.setItem('INDICADOR_SELECTOR', obj.indicador.label);
            toggleMenu(obj.$parent.$parent.node);
            toggleMenu(obj.$parent.$parent.node);
        }

      /**
        * Verifica se o item está ou não selecionado
        *
        * @method isSelected
		*        
        * @param obj {Object} Item da combo 
		*               
        */
        function isSelected(obj) {
            if (obj.indicador.label != null && obj.indicador.label == $window.sessionStorage.getItem('INDICADOR_SELECTOR')) {
                return true;
            } else {
                return false;
            }
        }


      /**
        * Escolhe um tema para o menu
        *
        * @method openThemeMenu
		*        
        * @param node {Object} Menu
		*               
        */
        function openThemeMenu(node) {

            $http.get(API_ENDPOINT + "tematico/" + node.categoriaId)
                .then(function (data) {

                    var confirm = $mdDialog.confirm({
                        templateUrl: 'app/directives/camadas/escolher_temas.html',
                        controller: function ($scope, $mdDialog) {

                            $scope.radioSelected;

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

                            $scope.salvar = function () {

                                showThemeMap($scope.radioSelected, $scope.data);
                            }

                            $scope.cancelar = function () {
                                $mdDialog.hide();
                            };
                        },
                        parent: angular.element(document.body)
                    });

                    $mdDialog.show(confirm)
                        .then(function () {

                        }, function () {
                            console.log('cancel');
                        });

                }, function (err) {
                    $mdDialog
                        .show($mdDialog.alert()
                            .title($scope.res('COMUM_ERRO'))
                            .content(err.data.message)
                            .ok('OK'));
                });
        }

        $scope.info;
        $scope.levelNumber = 5;
        $scope.themeLayers = [];
        $scope.markers = [];
        
      /**
        * Exibe os temas para o mapa
        *
        * @method showThemeMap
		*        
        * @param selectedInfo {Object}
        * @param poiData {Object}  Dados do poi
		*               
        */        
        function showThemeMap(selectedInfo, poiData) {

            var min = selectedInfo.min;
            var max = selectedInfo.max;
            var levels = createLevels(selectedInfo, min, max);

            angular.forEach($scope.themeLayers, function (object) {

                if (object.categoriaId == poiData.pois[0].CategoriumId) {
                    MapaService.removerCamada(object.layer);
                }
            });

            var mapElements = [];
            angular.forEach(poiData.pois, function (poi) {

                angular.forEach(poi.extras.informacoes, function (info) {

                    if (info.label == selectedInfo.nome) {

                        var element = {
                            type: 'Feature',
                            properties: {
                                valor: info.valor,
                                label: info.label,
                                id: poi.id
                            },
                            geometry: poi.geometry.geometry
                        }

                        mapElements.push(element);

                    }
                });

            });

            function style(feature) {
                return {
                    fillColor: getColor(levels, feature.properties.valor, min, max),
                    fillOpacity: 0.7,
                    weight: 1,
                    color: 'black'
                };
            }

            function onEachFeature(feature, layer) {

                layer.on({
                    contextmenu: MapaService.highlightFeature,
                    click: MapaService.clickPoi(feature.properties.id)
                });

                var center = getCentroid(feature.geometry);

                var marker = L.marker(center, {
                    icon: L.icon({
                        iconUrl: '/data-s4c/icons/SPC.png',
                        iconSize: [24, 24]
                    })
                });
                MapaService.addMarker(marker);
                $scope.markers.push(marker);

            }

            var featureCollection = {
                type: 'FeatureCollection',
                features: mapElements
            }

            var geojson = MapaService.adicionarGeoJSON(featureCollection, { style: style, onEachFeature: onEachFeature });
            MapaService.fitBounds(geojson.getBounds());

            CamadasService.ativarThemeMenu(poiData.pois[0]);

            $scope.themeLayers.push({ layer: geojson, categoriaId: poiData.pois[0].CategoriumId });

            $mdDialog.hide();
        }

      /**
        * Obtem a ponto central da geometria
        *
        * @method getCentroid
		*        
        * @param geometry {Object} Gemetry
		*               
        */   
        function getCentroid(geometry) {

            //Se for multipolygon, pega o que tiver mais pontos.
            var coordinates = [];

            if (geometry.coordinates.length > 1) {
                angular.forEach(geometry.coordinates, function (coordArray) {

                    if (coordArray[0].length > coordinates.length) {
                        coordinates = coordArray[0];
                    }
                });
            } else {
                coordinates = geometry.coordinates[0];
            }

            //obtem o menor x e y
            var minX = 1000;
            var minY = 1000;
            angular.forEach(coordinates, function (coord) {

                if (coord[0] <= minY) {
                    minY = coord[0];
                }

                if (coord[1] <= minX) {
                    minX = coord[1];
                }
            });

            //obtem o maior x e y
            var maxX = -1000;
            var maxY = -1000;
            angular.forEach(coordinates, function (coord) {

                if (coord[0] >= maxY) {
                    maxY = coord[0];
                }

                if (coord[1] >= maxX) {
                    maxX = coord[1];
                }
            });

            var center = [];
            center.push((minX + ((maxX - minX) / 2)), (minY + ((maxY - minY) / 2)));
            return center;
        }

      /**
        * Cria níveis 
        *
        * @method createLevels
		*        
        * @param selectedInfo {Object}
        * @param min {Integer} 
        * @param max {Integer}  
		*               
        */ 
        function createLevels(selectedInfo, min, max) {

            var difference = (max - min) / $scope.levelNumber;

            var levels = [];
            for (var i = 1; i < $scope.levelNumber; i++) {

                levels.push(min + i * difference);
            }

            return levels;
        }

        $scope.zeroColor = 'rgba(224,255,255,1)'; //branco
        $scope.maxColor = 'rgba(224,0,0,1)'; //vermelho
        
      /**
        * Obtem a cor para o nível específico 
        *
        * @method getColor
		*        
        * @param levels {Array} Levels
        * @param value {String} Color 
        * @param min {Integer} Mínimo
        * @param max {Integer} Máximo   
		*               
        */         
        function getColor(levels, value, min, max) {

            value = value.replace(',', '.');
            for (var i = 0; i < levels.length; i++) {

                if (value == 0) {
                    return $scope.zeroColor;
                }

                if (i == 0) {
                    if (value >= min && value < levels[i]) {
                        return 'rgba(224,255,170,1)';
                    }
                } else
                    if (i == levels.length - 1) {
                        if (value <= max && value >= levels[i]) {
                            return $scope.maxColor;
                        } else if (value >= levels[i - 1] && value < levels[i]) {
                            return 'rgba(224,' + (255 - getGreenValue() * i) + ',0,1)';
                        }
                    } else {

                        if (value >= levels[i - 1] && value < levels[i]) {
                            return 'rgba(224,' + (255 - getGreenValue() * i) + ',0,1)';
                        }
                    }
            }

        }
        
      /**
        * getGreenValue
        *
        * @method getGreenValue
		*        
		*               
        */  
        function getGreenValue() {

            var minGreenValue = 250;
            return Math.round(minGreenValue / $scope.levelNumber);
        }

        
      /**
        * Função chamada quando um item do menu camada é clicado
        *
        * @method toggleMenu
		*        
		* @param node {Object} Menu clicado              
        */  
        function toggleMenu(node) {
            node.ativo = !node.ativo;
            CamadasService.toggleMenu(node);

            if (!node.ativo) {
                angular.forEach($scope.themeLayers, function (object) {

                    if (object.categoriaId == node.categoriaId) {
                        MapaService.removerCamada(object.layer);
                    }
                });

                angular.forEach($scope.markers, function (object) {

                    MapaService.removerCamada(object);
                });
            }
        }

      /**
        * Verifica se a quantidade de subMenus é igual a de menus ativos  
        *
        * @method isIndeterminate
		*        
		* @param node {Object} Menu clicado              
        */ 
        function isIndeterminate(node) {
            return CamadasService.isIndeterminate(node);
        }

      /**
        * Verifica se o menu está desabilitado  
        *
        * @method isDisabled
		*        
		* @param node {Object} Menu clicado              
        */ 
        function isDisabled(node) {
            return CamadasService.isDisabled(node);
        }

      /**
        * Verifica se o menu está marcado  
        *
        * @method isChecked
		*        
		* @param node {Object} Menu clicado              
        */ 
        function isChecked(node) {
            return CamadasService.isChecked(node);
        }

      /**
        * Seleciona todos os menus  
        *
        * @method toggleTodos
		*        
		* @param grupo {Object} Grupo
        */ 
        function toggleTodos(grupo) {
            grupo.selecionarTodos = !grupo.selecionarTodos;
            _.each(grupo.subMenus, function (node) {
                node.ativo = !grupo.selecionarTodos;
            });

            _.each(grupo.subMenus, CamadasService.toggleMenu)
        }

      /**
        * Vincula a categoria ao preset atual, para no próximo login já vir marcado  
        *
        * @method vincularCategoriasPreset
		*        
		* 
        */ 
        function vincularCategoriasPreset() {
            var permissoes = $scope.permissoesExtras;
            var isPresetDeAgencia = Preset.isPresetDeAgencia();

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

            // Verificar se user tem permissão para modificar preset de grupo
            if (!permissoes.alterarPresetAgencia && isPresetDeAgencia) {
                toasty({
                    msg: $scope.res('COMUM_MSG_ALERT_EDITAR_PRESET')
                });
                return false;
            }
            CamadasService.vincularAoPreset();
        }

      /**
        * Verifica as permissões  
        *
        * @method hasPermission
		*        
		* @param node {Object} Menu 
        */ 
        function hasPermission(node) {

            if (!$scope.permissoesVisualizacao) {
                return true;
            }

            if (node.texto == $scope.res('BASECONHECIMENTO_TITULO_PLURAL')) {
                return $scope.permissoesVisualizacao.baseConhecimentoPublica;
            }

            if (node.texto == $scope.res('ZONAOBSERVACAO_TITULO_PLURAL')) {
                return $scope.permissoesVisualizacao.zonaObservacaoPublica;
            }

            if (node.texto == $scope.res('PLANEJAMENTO_TITULO_PLURAL')) {
                return $scope.permissoesVisualizacao.planejamentoPublico;
            }

            return true;
        }

        angular.extend($scope, {
            vincularCategoriasPreset: vincularCategoriasPreset,
            grupos: [],
            indicadores: CamadasService.indicadores,
            toggleMenu: toggleMenu,
            openThemeMenu,
            changeMapColor: changeMapColor,
            isSelected: isSelected,
            hasPermission: hasPermission,
            isToShowColorMapSelector: isToShowColorMapSelector,
            isChecked: isChecked,
            isIndeterminate: isIndeterminate,
            isDisabled: isDisabled,
            toggleTodos: toggleTodos,
            treeOptions: {
                nodeChildren: 'subMenus'
            },
            res: $scope.$root.res,
            expanded: $scope.expanded
        });
    }

}());