Source: components/admin/controllers/pois.controller.js

/**
 * @ngdoc controllers
 * @name Pois       
 * @module s4c.components.admin.controllers.Pois
 *
 * @description
 * `AdminPoisCtrl` Controller da tela de Poi do módulo de administração
 * 
 * 
 */
(function () {
    'use strict';

    AdminPoisCtrl.$inject = [
        '$scope',
        '$http',
        'Grupo',
        '$mdDialog',
        'API_ENDPOINT',
        'ngFileReader',
        'MapaEndereco',
        'Geocode',
        '$q',
        '$rootScope',
        'MapaAreaDeAtuacao',
        'leafletData',
        'CommService',
        'FileUploader',
        'Base',
        'MainState',
        'Poi'
    ];

    angular.module('s4c.controllers.AdminPoisCtrl', [
        's4c.services.Acervo',
        's4c.services.Grupo',
        's4c.services.Categoria',
        's4c.directives.ngFileReader'
    ]).controller('AdminPoisCtrl', AdminPoisCtrl);

    function AdminPoisCtrl($scope, $http, Grupo, $mdDialog, API_ENDPOINT,
        ngFileReader, MapaEndereco, Geocode, $q, $rootScope, MapaAreaDeAtuacao, leafletData, CommService, FileUploader, Base, MainState, Poi) {

        $scope.res = $rootScope.res;

        /**
         * @method exibirTipos
         * @param {*} row
         */
        $scope.exibirTipos = function (row) {
            var listObjetos = mapAtributos(row.entity.mensagem);

            if (listObjetos.length > 0) {
                //$scope.gridObjetoOptions.rowData = listObjetos;
                $scope.gridObjetoOptions.data = listObjetos;
            }
            else {
                $mdDialog
                    .show($mdDialog.alert()
                        .title($scope.res(audit.tipoObjeto))
                        .content($scope.res('AUDITORIA_FORMATO_TIPO_OBJETO'))
                        .ok($scope.res('COMUM_OK')));
                return;
            }

            $mdDialog.show({
                scope: $scope.$new(),
                template: '<md-dialog draggable>' +
                    '<md-title style="padding: 20px 0px 0px 20px;">' + $scope.res(row.entity.tipoObjeto) + '</md-title>' +
                    '<br>' +
                    '<div style="color: black;" flex md-theme="s4c-light">' +

                    ' <div ui-grid="gridObjetoOptions" class="grid">' +
                    ' </div>' +
                    '  <div class="md-actions">' +
                    '    <md-button ng-click="fechar()">' + $scope.res('COMUM_OK') + '</md-button>' +
                    '  </div>' +

                    '  </div>' +
                    '</md-dialog>',
                controller: function ($scope, $mdDialog) {
                    $scope.fechar = function () {
                        $mdDialog.hide();
                    }
                }
            });
        }

        $scope.tipos = [];
        var basicColumns = [];
        Poi.getTipos().then(function (resultado) {
            $scope.tipos = resultado;

            /**
             * @instance basicColumns
             * 
             */
            basicColumns = [{
                headerName: '',
                width: 30,
                checkboxSelection: true,
                suppressSorting: true,
                suppressMenu: true,
                cellClicked: fecharMapa
            }, {
                headerName: $scope.res('COMUM_NOME'),
                width: 130,
                field: 'nome',
                editable: true,
                cellClicked: fecharMapa
            }, {
                headerName: $scope.res('COMUM_DESCRICAO'),
                width: 350,
                field: 'descricao',
                editable: true,
                cellClicked: fecharMapa
            }, {
                headerName: $scope.res('COMUM_ENDERECO'),
                width: 100,
                field: 'endereco',
                editable: true,
                volatile: true,
                cellClicked: abrirMapa,
                newValueHandler: atualizarEndereco
            }, {
                headerName: $scope.res('COMUM_LATITUDE'),
                width: 100,
                field: 'latitude',
                editable: true,
                suppressSorting: true,
                volatile: true,
                newValueHandler: atualizarLatitude,
                cellClicked: abrirMapa
            }, {
                headerName: $scope.res('COMUM_LONGITUDE'),
                width: 100,
                field: 'longitude',
                editable: true,
                suppressSorting: true,
                volatile: true,
                cellClicked: abrirMapa,
                newValueHandler: atualizarLongitude
            }, {
                headerName: $scope.res('COMUM_URLICONE'),
                width: 150,
                field: 'urlIcone',
                editable: true,
                suppressSorting: true,
                cellClicked: fecharMapa
            }, {
                headerName: $scope.res('COMUM_CHAVEESTRANGEIRA'),
                width: 150,
                field: 'chave_estrangeira',
                editable: true,
                suppressSorting: true,
                cellClicked: fecharMapa
            }/*, {
                headerName: $scope.res('COMUM_TIPO'),
                width: 150,
                editable: false,
                field: 'tipoEntidade',
                cellTemplate: '<div style="text-align: center;"><a href="javascript:;"  ng-show="true" ng-click="grid.appScope.exibirTipos(row);"><img src="/assets/icons/search-icon-24px.png"></img></a></div>',
                suppressMenu: true,
                suppressSorting: true,
                cellClicked: fecharMapa
            }*/];

            if (MainState.isToShow('voip')) {
                basicColumns.push({
                    headerName: 'Ramal Voip',
                    width: 130,
                    field: 'ramalVoip',
                    editable: true,
                    cellClicked: fecharMapa
                });
            }

        });

        /**
         * @instance $scope.gridOptions
         */
        $scope.gridOptions = {
            rowSelection: 'multiple',
            rowDeselection: true,
            enableSorting: true,
            columnDefs: basicColumns,
            rowData: [],
            angularCompileHeaders: true,
            angularCompileRows: true,
            headerCellRenderer: headerCellRendererFunction,
            selectionChanged: onSelectionChanged,
            pinnedColumnCount: 1,
            enableColResize: true
        };

        leafletData
            .getMap('mapa-area-de-atuacao')
            .then(function (map) {

                map.on('draw:created', function (e) {

                    map.addLayer(e.layer);
                    e.layer.on('edit', function () {
                        MapaAreaDeAtuacao.trigger('areaDeAtuacaoEditada');
                    });
                    e.layer.editing.enable();
                    MapaAreaDeAtuacao._layer = e.layer;
                    MapaAreaDeAtuacao.trigger('areaDeAtuacaoEditada');
                })

                MapaAreaDeAtuacao._map = map;
            });

        /**
         * @method stringify
         * @param {*} gj 
         */
        function stringify(gj) {
            if (gj.type === 'Feature') {
                gj = gj.geometry;
            }

            function pairWKT(c) {
                if (c.length === 2) {
                    return c[1] + ' ' + c[0];
                } else if (c.length === 3) {
                    return c[0] + ' ' + c[1] + ' ' + c[2];
                }
            }

            function ringWKT(r) {
                return r.map(pairWKT).join(', ');
            }

            function ringsWKT(r) {
                return r.map(ringWKT).map(wrapParens).join(', ');
            }

            function multiRingsWKT(r) {
                return r.map(ringsWKT).map(wrapParens).join(', ');
            }

            /**
             * @method wrapParens
             * @param {*} s 
             */
            function wrapParens(s) { return '(' + s + ')'; }

            switch (gj.type) {
                case 'Point':
                    return 'POINT (' + pairWKT(gj.coordinates) + ')';
                case 'LineString':
                    return 'LINESTRING (' + ringWKT(gj.coordinates) + ')';
                case 'Polygon':
                    return 'POLYGON (' + ringsWKT(gj.coordinates) + ')';
                case 'MultiPoint':
                    return 'MULTIPOINT (' + ringWKT(gj.coordinates) + ')';
                case 'MultiPolygon':
                    return 'MULTIPOLYGON (' + multiRingsWKT(gj.coordinates) + ')';
                case 'MultiLineString':
                    return 'MULTILINESTRING (' + ringsWKT(gj.coordinates) + ')';
                case 'GeometryCollection':
                    return 'GEOMETRYCOLLECTION (' + gj.geometries.map(stringify).join(', ') + ')';
                default:
                    throw new Error('stringify requires a valid GeoJSON Feature or geometry object as input');
            }
        }

        /**
         * @method onFileSelected
         * @param {*} file 
         */
        function onFileSelected(file) {

            var json = KMLParser.loadKML(file.contents, ['Point', 'GeometryCollection', 'Polygon', 'MultiPolygon', 'LineString']);

            if (json.body.length == 0) {
                json = KMLParser.loadKMZ(file.contents, ['Point', 'GeometryCollection', 'Polygon', 'MultiPolygon', 'LineString']);
            }

            $scope.isKmlKmzUploaded = true;

            var rows = [];
            var poisNaoProcessados = 0;

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

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

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

                if (geojson.type === 'Point') {
                    var coordinates = JSON.parse(row[geojsonIndex]).coordinates;

                    return {
                        nome: row[nameIndex],
                        descricao: row[descriptionIndex],
                        latitude: coordinates[0],
                        longitude: coordinates[1]
                    };
                } else if (geojson.type === 'GeometryCollection') {
                    poiGeometrico = new Terraformer.GeometryCollection({
                        "type": "FeatureCollection",
                        "features": geojson.geometries
                    });

                } else if (geojson.type === 'Polygon') {
                    poiGeometrico = new Terraformer.Polygon({
                        "type": "Polygon",
                        "coordinates": geojson.coordinates
                    });

                } else if (geojson.type === 'MultiPolygon') {
                    poiGeometrico = new Terraformer.MultiPolygon({
                        "type": "MultiPolygon",
                        "coordinates": geojson.coordinates
                    });

                } else if (geojson.type === 'LineString') {

                    poiGeometrico = new Terraformer.LineString({
                        type: "LineString",
                        coordinates: geojson.coordinates
                    });

                } else {
                    poisNaoProcessados += 1;
                }

                return {

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

            }));
            if (poisNaoProcessados > 0) {
                $mdDialog.show($mdDialog.alert()
                    .title($scope.res('COMUM_ERRO'))
                    .content($scope.res('ARQUIVO_KMLKMZERRO_1') + poisNaoProcessados + $scope.res('ARQUIVO_KMLKMZERRO_2') + rows.length)
                    .ok($scope.res('COMUM_OK')));
            }

            _montarGrid(rows);
        }

        ngFileReader.on('fileSelectedPOI', onFileSelected);
        /**
         * @method atualizarCoordenadas
         * @param {*} coordenadas
         */
        MapaEndereco.on('atualizarCoordenadas', function (coordenadas) {
            if ($scope.gridOptions != null && $scope.gridOptions.selectedRows != null && $scope.gridOptions.selectedRows.length === 1) {
                var row = $scope.gridOptions.selectedRows[0];

                row.latitude = coordenadas.latitude;
                row.longitude = coordenadas.longitude;
                row.endereco = coordenadas.endereco;

                $scope.gridOptions.api.refreshView();
            }
        });

        $scope.exibeMapa = false;
        $scope.lastSelectedRow = {};
        $scope.$on('$destroy', function () {
            MapaEndereco.limparEventos();
        });

        /**
         * @method _montarGrid
         * @param {*} row 
         * @param {*} columnDefs 
         */
        function _montarGrid(row, columnDefs) {
            var promises = [];
            var promisesAsync = [];

            $scope.gridOptions.columnDefs = columnDefs || basicColumns.slice();

            var extraColumns = obterColunasExtras(row);

            _.each(row, function (poi) {

                if (poi.extras) {
                    _.each(extraColumns, function (extraColumn) {
                        _.each(poi.extras.informacoes, function (extra) {
                            if (extra.label == extraColumn.headerName) {
                                poi[extraColumn.field] = extra.valor;
                            }
                        });
                    });
                }

                if (((poi.poiGeometrico) && (!poi.poiGeometrico.type || poi.poiGeometrico.type === 'Point')) || (poi.latitude != null && poi.longitude != null)) {

                    if (!poi.latitude && !poi.longitude) {
                        if (poi.poiGeometrico && JSON.parse(poi.poiGeometrico).type == 'Point') {
                            poi.latitude = JSON.parse(poi.poiGeometrico).coordinates[1];
                            poi.longitude = JSON.parse(poi.poiGeometrico).coordinates[0];
                        }
                    }
                }

                poi._id = _.uniqueId();
            });

            $q.all(promises).then(function () {
                if ($scope.gridOptions.api)
                    $scope.gridOptions.api.softRefreshView();
            });

            $q.all(promisesAsync).then(function () {
                if ($scope.gridOptions.api)
                    $scope.gridOptions.api.softRefreshView();
            });

            var actualExtraColumns = obterColunasExtras($scope.gridOptions.rowData);

            extraColumns = extraColumns.concat(actualExtraColumns);

            $scope.gridOptions.columnDefs = $scope.gridOptions.columnDefs.concat(extraColumns);

            $scope.gridOptions.columnDefs.push({
                headerName: '+',
                field: '',
                width: 30,
                suppressSorting: true,
                cellClicked: adicionarColuna
            });

            if ($scope.gridOptions.rowData != null && $scope.gridOptions.rowData.length > 0) {
                _.each(row, function (linha) {
                    $scope.gridOptions.rowData.push(linha);
                });
            } else {
                $scope.gridOptions.rowData = row;
            }

            if ($scope.gridOptions.api) {
                $scope.gridOptions.api.onNewCols();
                $scope.gridOptions.api.onNewRows();
                $scope.gridOptions.api.setSortModel([{
                    field: 'nome',
                    sort: 'asc'
                }]);
            }

            return $q.all(promises.concat(promisesAsync));
        }

        /**
         * @method obterColunasExtras
         * @param {*} rows 
         */
        function obterColunasExtras(rows) {
            return _.chain(rows)
                .filter('extras')
                .map('extras.informacoes')
                .flatten()
                .uniqBy('label')
                .map(function (extra) {
                    var coluna = {};
                    coluna.nome = extra.label;

                    if (extra.tipo) {
                        coluna.tipo = extra.tipo;
                    }

                    return _obterColunaExtra(coluna);
                }).value();
        }

        /**
         * @method _obterColunaExtra
         * @param {*} coluna 
         */
        function _obterColunaExtra(coluna) {
            if (!coluna.tipo) {
                coluna.tipo = ""
            }

            return {
                headerName: coluna.nome,
                field: 'extra-' + coluna.nome + "-" + coluna.tipo + '-' + coluna.perfis,
                editable: true,
                headerCellRenderer: extraHeaderRenderer,
                suppressMenu: false,
                suppressSorting: true,
                cellClicked: fecharMapa,
                tipo: coluna.tipo
            }
        }

        /**
         * @method atualizarLatitude
         * @param {*} params 
         */
        function atualizarLatitude(params) {
            var latitude = params.newValue;
            var longitude = params.data.longitude;
            MapaEndereco.atualizarCoordenadas(latitude, longitude);
        }

        /**
         * @method atualizarLongitude
         * @param {*} params 
         */
        function atualizarLongitude(params) {
            var latitude = params.data.latitude;
            var longitude = params.newValue;
            MapaEndereco.atualizarCoordenadas(latitude, longitude);
        }

        /**
         * @method atualizarEndereco
         * @param {*} params 
         */
        function atualizarEndereco(params) {
            MapaEndereco.atualizarEndereco(params.newValue);
        }

        MapaAreaDeAtuacao.on('areaDeAtuacaoEditada', function (data) {
            $scope.lastSelectedRow.poiGeometrico = data.geojson;
            $scope.lastSelectedRow.novaLinha = false;
        });

        /**
         * @method onSelectionChanged
         */
        function onSelectionChanged() {
            if ($scope.gridOptions != null && $scope.gridOptions.selectedRows != null && $scope.gridOptions.selectedRows.length === 1 && $scope.exibeMapa) {
                var row = $scope.gridOptions.selectedRows[0];

                if (row._id != $scope.lastSelectedRow._id) {
                    if ((row.latitude && row.longitude) || (!row.poiGeometrico)) {
                        MapaEndereco.atualizarCoordenadas(row.latitude, row.longitude);
                    } else {
                        MapaAreaDeAtuacao.atualizarArea(row.poiGeometrico, { desenhar: false });
                    }
                    $scope.lastSelectedRow = row;
                }
            } else {
                fecharMapa();
            }
        }

        /**
         * @method checkboxClick
         */
        function checkboxClick(params) {
            fecharMapa();
            angular.element(params.eventSource).find('input').click();
            params.event.stopPropagation();
        }

        /**
         * @method extraHeaderRenderer
         * @param {*} params 
         */
        function extraHeaderRenderer(params) {
            var eHeader = document.createElement('span');
            var eTitle = document.createTextNode(params.colDef.headerName);
            var eEdit = createEditButton(params);
            eHeader.setAttribute('ng-dblclick', 'editarColuna(this, "' + params.colDef.field + '")');

            eHeader.appendChild(eTitle);

            if (isExtraField(params.colDef.field)) {
                var removeButton = createRemoveButton(params);
                eHeader.appendChild(removeButton);
            }
            eHeader.appendChild(eEdit);

            eHeader.style.color = 'darkgrey';
            return eHeader;
        }

        /**
         * @method createEditButton
         * @param {*} params 
         */
        function createEditButton(params) {
            var editButton = document.createElement('md-icon');
            editButton.setAttribute('class', 'menu-icon');
            editButton.setAttribute('style', 'float:right');
            editButton.setAttribute('md-svg-icon', 'menu:edit');
            editButton.setAttribute('alt', 'editar');
            editButton.setAttribute('ng-click', 'editarColuna($event, this,"' + params.colDef.field + '")');
            return editButton;
        }

        /**
         * @method createRemoveButton
         * @param {*} params 
         */
        function createRemoveButton(params) {
            var removeButton = document.createElement('md-icon');
            removeButton.setAttribute('class', 'menu-icon');
            removeButton.setAttribute('style', 'float:right');
            removeButton.setAttribute('md-svg-icon', 'menu:delete');
            removeButton.setAttribute('alt', 'remover');
            removeButton.setAttribute('ng-click', 'removerColuna($event, this,"' + params.colDef.field + '")');
            return removeButton;
        }

        /**
         * @method isExtraField
         * @param {*} field 
         */
        function isExtraField(field) {
            return field.includes('extra');
        }

        /**
         * @method headerCellRendererFunction
         * @param {*} params 
         */
        function headerCellRendererFunction(params) {

            var eHeader = document.createElement('span');
            var eTitle = document.createTextNode(params.colDef.headerName);

            eHeader.appendChild(eTitle);


            if (params.colDef.headerName == '') {
                eHeader.style.textAlign = 'center';
                eHeader.style.verticalAlign = 'center';
            } else if (params.colDef.headerName == '+') {

                eHeader.setAttribute('ng-click', 'adicionarColuna(this)');

            } else if (params.colDef.headerName !== $scope.res('AREA')) {

                var eEdit = createEditButton(params);
                eHeader.appendChild(eEdit);

            } else {

                var eEdit = createEditButton(params);
                eEdit.setAttribute('style', 'float:right');
                eHeader.appendChild(eEdit);
            }

            return eHeader.outerHTML;
        }

        /**
         * @method abrirMapa
         * 
         */
        function abrirMapa() {
            $scope.exibeMapa = true;
        }

        /**
         * @method fecharMapa
         */
        function fecharMapa() {
            $scope.exibeMapa = false;
        }

        /**
         * @method definirValorDaColuna 
         * 
         * @param {*} event 
         * @param {*} domNode 
         * @param {*} field 
         */
        function definirValorDaColuna(event, domNode, field) {
            event.stopPropagation();
            $mdDialog.show({
                controller: function ($scope, res) {
                    $scope.res = res;
                    $scope.tiposExtra = [{ "label": res('SEM_TIPO'), "value": "" }, { "label": res('Camera'), "value": "CAMERA" }, { "label": res('Camera Wowza'), "value": "CAMERA_WOWZA" }, { "label": "HTML", "value": "HTML" }, { "label": res('COMUM_IMAGEM'), "value": "IMAGE" }, { "label": "INDICADOR", "value": "INDICADOR" }];
                    $scope.visibilidadesExtra = [{ "label": res('Visível'), "value": "TRUE" }, { "label": res('Não Visível'), "value": "FALSE" }, { "label": res('Visível somente para alguns perfis'), "value": "PERFIL" }];

                    $scope.isToShowPerfis = function () {
                        if ($scope.coluna != null && $scope.coluna.VISIBILIDADE != null && $scope.coluna.VISIBILIDADE == "PERFIL") {
                            return true;
                        } else {
                            return false;
                        }
                    }

                    $http.get(API_ENDPOINT + 'perfil/').then(function (response) {
                        if (typeof response.data === 'object') {
                            $scope.perfis = _.map(response.data, function (perfil) {
                                if (perfil.GrupoUsuarioId != null) {
                                    return {
                                        id: perfil.id,
                                        nome: perfil.grupoNome + " - " + perfil.nome,
                                        val: false,
                                        permissoesAcesso: perfil.PermissaoAcessos,
                                        departamentoId: perfil.DepartamentoId
                                    };
                                }
                            });

                            $scope.perfis = _.filter($scope.perfis, function (perfil_) {
                                return perfil_ != null && perfil_.nome != null;
                            });
                        } else {
                            console.log(response.data);
                        }
                    }, function (response) {
                        console.log(response.data);
                    });

                    $scope.ok = function () {
                        if (typeof $scope.coluna.VISIBILIDADE !== "boolean") {
                            $scope.coluna.VISIBILIDADE = $scope.coluna.perfis;
                        }
                        $mdDialog.hide($scope.coluna.valor);
                    };

                    $scope.cancelar = $mdDialog.cancel;
                },
                templateUrl: 'app/components/admin/modulos/manutencao/pois/definirValorDaColuna.html',
                parent: domNode,
                locals: {
                    res: $scope.res
                }
            }).then(function (valor) {
                _.each($scope.gridOptions.rowData, function (row) {
                    row[field] = valor;
                });
                $scope.gridOptions.api.refreshView();
            });
        }

        /**
         * @method removerColuna
         * 
         * @param {*} domNode 
         * @param {*} field 
         */
        function removerColuna(domNode, field){
            var confirm = $mdDialog.confirm()
                .title($scope.res('COMUM_AVISO'))
                .content($scope.res('REMOVER_EXTRA'))
                .ok($scope.res('COMUM_SIM'))
                .cancel($scope.res('COMUM_CANCELAR'));

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

                    _.each($scope.gridOptions.rowData, function (row) {
                        row[field.colDef.field] = undefined;
                        delete row[field.colDef.field];
                    });

                   removeColumnFromGridOptions(field);

                    $scope.gridOptions.api.onNewCols();
                    $scope.gridOptions.api.refreshView();

                }, function () {
                });
        }

        /**
         * @method removeColumnFromGridOptions
         * @param {*} field 
         */
        function removeColumnFromGridOptions(field){
            $scope.gridOptions.columnDefs = _.filter($scope.gridOptions.columnDefs, function(colDef){
                return colDef.headerName != field.colDef.headerName;
            });
        }

        /**
         * @method editarColuna
         * 
         * @param {*} domNode 
         * @param {*} field 
         */
        function editarColuna(domNode, field) {

            $mdDialog.show({
                controller: function ($scope, modo, res) {
                    $scope.coluna = { nome: "" };
                    $scope.coluna.nome = field.colDef.headerName;
                    $scope.coluna.tipo = field.colDef.tipo;
                    $scope.modo = modo;
                    $scope.res = res;
                    $scope.tiposExtra = [{ "label": res('SEM_TIPO'), "value": "" }, { "label": res('Camera'), "value": "CAMERA" }, { "label": res('Camera Wowza'), "value": "CAMERA_WOWZA" }, { "label": "HTML", "value": "HTML" }, { "label": res('COMUM_IMAGEM'), "value": "IMAGE" }, { "label": "INDICADOR", "value": "INDICADOR" }];
                    $scope.visibilidadesExtra = [{ "label": res('Visível'), "value": "TRUE" }, { "label": res('Não Visível'), "value": "FALSE" }, { "label": res('Visível somente para alguns perfis'), "value": "PERFIL" }];

                    $scope.isToShowPerfis = function () {
                        if ($scope.coluna != null && $scope.coluna.VISIBILIDADE != null && $scope.coluna.VISIBILIDADE == "PERFIL") {
                            return true;
                        } else {
                            return false;
                        }
                    }

                    $http.get(API_ENDPOINT + 'perfil/').then(function (response) {
                        if (typeof response.data === 'object') {
                            $scope.perfis = _.map(response.data, function (perfil) {
                                if (perfil.GrupoUsuarioId != null) {
                                    return {
                                        id: perfil.id,
                                        nome: perfil.grupoNome + " - " + perfil.nome,
                                        val: false,
                                        permissoesAcesso: perfil.PermissaoAcessos,
                                        departamentoId: perfil.DepartamentoId
                                    };
                                }
                            });

                            $scope.perfis = _.filter($scope.perfis, function (perfil_) {
                                return perfil_ != null && perfil_.nome != null;
                            });

                        }
                    }, function (response) {
                        console.log(response.data);
                    });

                    $scope.ok = function () {
                        if (typeof $scope.coluna.VISIBILIDADE !== "boolean") {
                            $scope.coluna.VISIBILIDADE = $scope.coluna.perfis;
                        }
                        $mdDialog.hide($scope.coluna);
                    };

                    $scope.cancelar = $mdDialog.cancel;
                },
                templateUrl: 'app/components/admin/modulos/manutencao/pois/editarColuna.html',
                parent: domNode,
                locals: {
                    modo: $scope.res('COMUM_EDITAR'),
                    res: $scope.res
                }

            }).then(function (coluna) {
                var oldName = field;

                _.each($scope.gridOptions.rowData, function (row) {
                    row['extra-' + coluna.nome + '-' + coluna.tipo] = angular.copy(row[oldName.colDef.field]);
                    row[oldName.colDef.field] = undefined;
                    delete row[oldName.colDef.field];
                });

                field.colDef.headerName = coluna.nome;
                field.colDef.field = 'extra-' + coluna.nome + '-' + coluna.tipo + '-' + coluna.perfis,
                    field.colDef.tipo = coluna.tipo;

                $scope.gridOptions.api.onNewCols();
                $scope.gridOptions.api.refreshView();
            });
        }

        /**
         * @method adicionarColuna
         * 
         * @param {*} domNode 
         */
        function adicionarColuna(domNode) {

            $mdDialog.show({
                controller: function ($scope, modo, res) {
                    $scope.modo = modo;
                    $scope.res = res;
                    $scope.tiposExtra = [{ "label": res('SEM_TIPO'), "value": "" }, { "label": res('Camera'), "value": "CAMERA" }, { "label": res('Camera Wowza'), "value": "CAMERA_WOWZA" }, { "label": "HTML", "value": "HTML" }, { "label": res('COMUM_IMAGEM'), "value": "IMAGE" }, { "label": "INDICADOR", "value": "INDICADOR" }];
                    $scope.visibilidadesExtra = [{ "label": res('Visível'), "value": "TRUE" }, { "label": res('Não Visível'), "value": "FALSE" }, { "label": res('Visível somente para alguns perfis'), "value": "PERFIL" }];

                    $scope.isToShowPerfis = function () {
                        if ($scope.coluna != null && $scope.coluna.VISIBILIDADE != null && $scope.coluna.VISIBILIDADE == "PERFIL") {
                            return true;
                        } else {
                            return false;
                        }
                    }


                    $http.get(API_ENDPOINT + 'perfil/').then(function (response) {
                        if (typeof response.data === 'object') {
                            $scope.perfis = _.map(response.data, function (perfil) {
                                if (perfil.GrupoUsuarioId != null) {
                                    return {
                                        id: perfil.id,
                                        nome: perfil.grupoNome + " - " + perfil.nome,
                                        val: false,
                                        permissoesAcesso: perfil.PermissaoAcessos,
                                        departamentoId: perfil.DepartamentoId
                                    };
                                }
                            });

                            $scope.perfis = _.filter($scope.perfis, function (perfil_) {
                                return perfil_ != null && perfil_.nome != null;
                            });

                        }
                    }, function (response) {
                        console.log(response.data);
                    });

                    $scope.ok = function () {
                        if (typeof $scope.coluna.VISIBILIDADE !== "boolean") {
                            $scope.coluna.VISIBILIDADE = $scope.coluna.perfis;
                        }
                        $mdDialog.hide($scope.coluna);
                    };

                    $scope.cancelar = $mdDialog.cancel;
                },
                templateUrl: 'app/components/admin/modulos/manutencao/pois/definirValorDaColuna.html',
                parent: domNode,
                locals: {
                    modo: $scope.res('COMUM_ADICIONAR'),
                    res: $scope.res
                }
            }).then(function (coluna) {

                coluna = _obterColunaExtra(coluna);
                $scope.gridOptions.columnDefs.pop();
                $scope.gridOptions.columnDefs.push(coluna);
                $scope.gridOptions.columnDefs.push({
                    headerName: "+",
                    field: '',
                    width: 30,
                    suppressSorting: true
                });

                _.each($scope.gridOptions.rowData, function (row) {
                    row[coluna.field] = "";
                });

                $scope.gridOptions.api.onNewCols();
            });
        }

        /**
         * @method deletarSelecionados
         * 
         */
        function deletarSelecionados() {

            var confirm = $mdDialog.confirm()
                .title($scope.res('COMUM_AVISO'))
                .content($scope.res('PERGUNTA_DELETAR_POI'))
                .ok($scope.res('COMUM_SIM'))
                .cancel($scope.res('COMUM_CANCELAR'));

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

                    var selecionados = _.map($scope.gridOptions.api.getSelectedNodes(), 'data._id');
                    var ids = _.map($scope.gridOptions.api.getSelectedNodes(), 'data.id');

                    _.remove($scope.gridOptions.rowData, function (row) {
                        return _.includes(selecionados, row._id)
                    });

                    $scope.gridOptions.api.onNewRows();

                    $http.post(API_ENDPOINT + "pois/deletePois", ids)
                        .then(function () {
                        });
                }, function () {
                });
        }

        /**
         * Converte um geojson para o formato WKT
         * @method convertGeojsonToWKT
         * @param {*} gj
         */
        function convertGeojsonToWKT(gj) {
            if (gj.type === 'Feature') {
                gj = gj.geometry;
            }

            function pairWKT(c) {
                if (c.length === 2) {
                    return c[1] + ' ' + c[0];
                } else if (c.length === 3) {
                    return c[0] + ' ' + c[1] + ' ' + c[2];
                }
            }

            function ringWKT(r) {
                return r.map(pairWKT).join(', ');
            }

            function ringsWKT(r) {
                return r.map(ringWKT).map(wrapParens).join(', ');
            }

            function multiRingsWKT(r) {
                return r.map(ringsWKT).map(wrapParens).join(', ');
            }

            function wrapParens(s) { return '(' + s + ')'; }

            switch (gj.type) {
                case 'Point':
                    return 'POINT (' + pairWKT(gj.coordinates) + ')';
                case 'LineString':
                    return 'LINESTRING (' + ringWKT(gj.coordinates) + ')';
                case 'Polygon':
                    return 'POLYGON (' + ringsWKT(gj.coordinates) + ')';
                case 'MultiPoint':
                    return 'MULTIPOINT (' + ringWKT(gj.coordinates) + ')';
                case 'MultiPolygon':
                    return 'MULTIPOLYGON (' + multiRingsWKT(gj.coordinates) + ')';
                case 'MultiLineString':
                    return 'MULTILINESTRING (' + ringsWKT(gj.coordinates) + ')';
                case 'GeometryCollection':
                    return 'GEOMETRYCOLLECTION (' + gj.geometries.map(stringify).join(', ') + ')';
                default:
                    throw new Error('stringify requires a valid GeoJSON Feature or geometry object as input');
            }
        }

        /**
         * @method salvar
         */
        function salvar() {

            var rows = $scope.gridOptions.rowData;
            var contentMessage = '';
            var containsErroNomeVazio = false;
            var containsErroLatVazio = false;
            var containsErroLongVazio = false;
            var containsErroChaveEstrangeiraVazio = false;

            for (var index in rows) {
                if (!_.trim(rows[index].nome) && !containsErroNomeVazio) {
                    containsErroNomeVazio = true;
                    contentMessage += '' + $scope.res('EXCEL_NOME_VALUE_VAZIO') + ' <br> ';
                }
                if (!_.trim(rows[index].latitude) && !containsErroLatVazio && ((rows[index].geometry != null && rows[index].geometry.type === 'Point') || rows[index].tipo === 'POINT')) {
                    containsErroLatVazio = true;
                    contentMessage += '' + $scope.res('EXCEL_LAT_VALUE_VAZIO') + ' <br> ';
                }
                if (!_.trim(rows[index].longitude) && !containsErroLongVazio && ((rows[index].geometry != null && rows[index].geometry.type === 'Point') || rows[index].tipo === 'POINT')) {
                    containsErroLongVazio = true;
                    contentMessage += '' + $scope.res('EXCEL_LONG_VALUE_VAZIO') + ' <br> ';
                }
                if (!_.trim(rows[index].chave_estrangeira) && !containsErroChaveEstrangeiraVazio && !$scope.isKmlKmzUploaded) {
                    containsErroChaveEstrangeiraVazio = true;
                    contentMessage += '' + $scope.res('EXCEL_CHAVE_ESTRANGEIRA_VALUE_VAZIO') + ' <br> ';
                }
            }

            if (_.trim(contentMessage)) {
                $mdDialog.show({
                    controller: function ($scope, $mdDialog) {
                        $scope.res = $scope.$root.res;
                        $scope.fechar = function () {
                            $mdDialog.hide();
                        }
                    },
                    template: '<md-dialog  style="width: 600px;">' +
                        '<md-title style="padding: 20px 0px 0px 20px;">Erro</md-title>' +
                        ' <md-content> ' + contentMessage + ' </md-content> ' +
                        '  <div class="md-actions">' +
                        '    <md-button ng-click="fechar()">' + $scope.res('COMUM_OK') + '</md-button>' +
                        '  </div>' +
                        '</md-dialog>'
                });
                return;
            }

            for (var index in rows) {

                rows[index].extras = {
                    informacoes: []
                };

                for (var index2 in Object.keys(rows[index])) {
                    if (_.startsWith(Object.keys(rows[index])[index2], 'extra-')) {

                        var split = Object.keys(rows[index])[index2].split("-");
                        var label = split[1];
                        var tipo = split[2];

                        if (tipo == "undefined") {
                            tipo = "";
                        }

                        rows[index].extras.informacoes.push({
                            label: label,
                            valor: rows[index][Object.keys(rows[index])[index2]] ? rows[index][Object.keys(rows[index])[index2]] : " ",
                            tipo: tipo
                        });
                    }

                    if (rows[index].latitude && rows[index].longitude && !rows[index].geojson && (!rows[index].geometry || rows[index].geometry.type == 'Point')) {
                        rows[index].poiGeometrico = 'SRID=4326;POINT(' + rows[index].longitude + ' ' + rows[index].latitude + ')';
                    } else {
                        rows[index].poiGeometrico = 'SRID=4326;' + convertGeojsonToWKT(rows[index].geojson || rows[index].geometry);
                    }

                    if (rows[index].endereco == $scope.res('COMUM_CARREGANDO')) {
                        rows[index].endereco = null;
                    }
                }

                delete rows[index].geojson;
            }

            $http.post(API_ENDPOINT + "pois/manutencao", {
                categoria: $scope.categoriaId,
                pois: rows
            })
                .then(function () {
                    $mdDialog
                        .show($mdDialog.alert()
                            .title($scope.res('COMUM_SUCESSO'))
                            .content($scope.res('MENSAGEM_SUCESSO_ATUALIZACAO_POI'))
                            .ok('OK'));
                    $scope.isKmlKmzUploaded = false;
                });
        }

        /**
         * @method ErroNoImportDoExcel
         * @param {*} data
         */
        CommService.on('ErroNoImportDoExcel', function (data) {
            var contentMessage = '';
            for (var index in data.ERRO) {
                contentMessage += '' + $scope.res(data.ERRO[index].ERROR) + ' <br> ';
            }

            $mdDialog.show({
                controller: function ($scope, $mdDialog) {
                    $scope.res = $scope.$root.res;
                    $scope.fechar = function () {
                        $mdDialog.hide();
                    }
                },
                template: '<md-dialog  style="width: 600px;">' +
                    '<md-title style="padding: 20px 0px 0px 20px;">Erro</md-title>' +
                    ' <md-content> ' + contentMessage + ' </md-content> ' +
                    '  <div class="md-actions">' +
                    '    <md-button ng-click="fechar()">' + $scope.res('COMUM_OK') + '</md-button>' +
                    '  </div>' +
                    '</md-dialog>'
            });
        });

        /**
         * @method ativarGrupo
         */
        function ativarGrupo() {
            var grupo = JSON.parse($scope.grupo);

            if (grupo.ativo) {
                return;
            }

            $scope.grupos = _.map($scope.grupos, function (grupo) {
                grupo.ativo = false;
                return grupo;
            });

            $scope.acervos = _.map(grupo.Acervos, function (acervo) {
                acervo.ativo = false;
                return acervo;
            });

            grupo.ativo = true;
            $scope.categorias = [];
            $scope.acervoAtivo = true;

        }

        /**
         * @method ativarAcervo
         */
        function ativarAcervo() {

            var acervo = JSON.parse($scope.acervo);

            $scope.acervos = _.map($scope.acervos, function (acervo) {
                acervo.ativo = false;
                return acervo;
            });

            acervo.ativo = true;

            $scope.categorias = acervo.Categoria;
            $scope.categoriaAtiva = true;
        }

        /**
         * @method ativarCategoria
         */
        function ativarCategoria() {
            var categoria = JSON.parse($scope.categoria);

            $scope.categoriaNome = categoria.nome;
            $scope.categoriaId = categoria.id;

            $scope.gridOptions.rowData = [];

            return $http.get(API_ENDPOINT + 'pois/integracao/categoria/' + categoria.id)
                .then(function (res) {

                    $scope.gridOptions.columnDefs = basicColumns.slice();
                    return _montarGrid(res.data)

                }, function (err) {
                    console.log(err);
                });

        }

        /**
         * @method adicionarNovaLinha
         */
        function adicionarNovaLinha() {
            $scope.gridOptions.rowData.unshift({
                CategoriumId: $scope.categoriaId
            });
            $scope.gridOptions.api.onNewRows();
            $scope.gridOptions.api.setSortModel($scope.gridOptions.api.getSortModel());
        }


        $scope.input = angular.element('input.uploadArquivo');

        var uploader = $scope.uploader = new FileUploader(),
            uploadCallbackQueue = [];

        uploader.clearQueue();

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

        $scope.uploader.filters.push({
            'name': 'enforceMaxFileSize',
            'fn': function (item, evt) {

                $scope.tamFile = item.size;

                return true;
            }
        });

        $scope.uploader.onCompleteItem = function (item, response) {
            $scope.mensagem = response;
        };

        $scope.uploader.onAfterAddingFile = function (item, evt, arquivo) {
            item.novoNome = item.file.name;
            enviarArquivo();
        }

        /**
         * @method enviarArquivo
         */
        function enviarArquivo() {
            if ($scope.tamFile > 35000) {
                $mdDialog
                    .show($mdDialog.alert()
                        .title($scope.res('COMUM_AVISO'))
                        .content($scope.res('EXCEL_POI_EM_PROCESSAMENTO'))
                        .ok($scope.res('COMUM_OK')));
            }

            $scope.isUploading = true;
            uploader.url = '/pois/file/add/' + JSON.parse($scope.categoria).id;
            uploader.uploadAll();
            $scope.gridOptions.rowData = [];
            uploadCallbackQueue = [];
            uploadCallbackQueue.push(function () {
                $scope.isUploading = false;
                $scope.arquivosPraSubir = false;
                uploader.clearQueue();
                ativarCategoria();

                $mdDialog
                    .show($mdDialog.alert()
                        .title($scope.res('COMUM_AVISO'))
                        .content($scope.res('EXCEL_POI_PROCESSADO'))
                        .ok($scope.res('COMUM_OK')));

            });
        }

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

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

        $scope.uploader.onProgressItem = function (fileItem, progress) {
            console.info('onProgressItem', fileItem, progress);
            //listaEquals = [];
        };

        $scope.uploader.onCompleteAll = function (result) {
            _.each(uploadCallbackQueue, function (callback) {
                callback();
            });
        };

        $scope.importFile = function () {
            $("#arquivo").click();
        };

        /**
         * @method exportarPoiExcel
         */
        $scope.exportarPoiExcel = function () {

            var data = {};
            var rows = $scope.gridOptions.rowData;

            for (var index in rows) {

                rows[index].extras = {
                    informacoes: []
                };

                for (var index2 in Object.keys(rows[index])) {
                    if (_.startsWith(Object.keys(rows[index])[index2], 'extra-')) {

                        var split = Object.keys(rows[index])[index2].split("-");
                        var label = split[1];
                        var tipo = split[2];

                        if (tipo == "undefined") {
                            tipo = "";
                        }

                        rows[index].extras.informacoes.push({
                            label: label,
                            valor: rows[index][Object.keys(rows[index])[index2]] ? rows[index][Object.keys(rows[index])[index2]] : " ",
                            tipo: tipo
                        });
                    }
                }
            }

            data.pois = rows;
            data.headers = [];

            for (var index in $scope.gridOptions.columnDefs) {
                if ($scope.gridOptions.columnDefs[index].headerName != null && $scope.gridOptions.columnDefs[index].headerName != "" && $scope.gridOptions.columnDefs[index].headerName != "+") {
                    data.headers.push($scope.gridOptions.columnDefs[index].headerName);
                }
            }

            $http
                .post(API_ENDPOINT + 'pois/excel/download', data, { responseType: 'arraybuffer', })
                .then(function (res) {

                    var a = document.createElement("a");
                    document.body.appendChild(a);
                    a.style = "display: none";

                    var file = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
                    var fileURL = URL.createObjectURL(file);

                    a.href = fileURL;
                    a.download = JSON.parse($scope.categoria).nome + ".xlsx";
                    a.click();

                    $mdDialog
                        .show($mdDialog.alert()
                            .title($scope.res('COMUM_SUCESSO'))
                            .content('Arquivo gerado com sucesso.')
                            .ok($scope.res('COMUM_OK')));
                }, function (err) {
                    console.log(err);
                });
        };

        angular.extend($scope, {
            removerColuna: removerColuna,
            editarColuna: editarColuna,
            adicionarColuna: adicionarColuna,
            definirValorDaColuna: definirValorDaColuna,
            adicionarNovaLinha: adicionarNovaLinha,
            grupos: Grupo.query(),
            ativarGrupo: ativarGrupo,
            fecharMapa: fecharMapa,
            ativarAcervo: ativarAcervo,
            ativarCategoria: ativarCategoria,
            deletarSelecionados: deletarSelecionados,
            salvar: salvar
        });
    }
}());