Source: directives/mapa/planejamento-desenho/planejamento-desenho.service.js

(function () {
    'use strict';

    PlanejamentoDesenhoService.$inject = ['$http', '$q', 'MainState', 'MapaService'];

    angular.module('s4c.components.mapa')
        .service('PlanejamentoDesenhoService', PlanejamentoDesenhoService);

    /**
     * @ngdoc directives
     * @name PlanejamentoDesenhoService
     * @module s4c.directives.mapa.PlanejamentoDesenho.PlanejamentoDesenhoService
     *
     * @description
     * Singleton que gerencia o box de desenho de planejamento.
     */

    /**
     * @method PlanejamentoDesenhoService
     * @param {*} $http 
     * @param {*} $q 
     * @param {*} MainState 
     * @param {*} MapaService 
     */
    function PlanejamentoDesenhoService($http, $q, MainState, MapaService) {
        var that = this;
        var geocoder = new L.Control.Geocoder.Google();
        var Icon = L.divIcon({
            html: '<div class="planejamento-icone-wrapper" style="background-image: url(\'/assets/images/Pegmans/ic_pegman_bombeiro_48px.svg\');"><b class="marker-cluster-counter">' + 1 + '</b></div>',
            iconSize: [48, 48],
        });

        this.texto = '';
        var icon = Icon;

        this.alturaCaixaDesenho = {}
        this.state = {
            isVisible: false
        };

      /**
       * @method definirCorPreenchimento
       * @param {*} cor 
       */
        function definirCorPreenchimento(cor) {
            if (this.layerAtual && !this.layerAtual.options.icon) {
                this.layerAtual.setStyle({
                    fillColor: cor
                });
            }
        }

        /**
         * @method alterarQuantidadeIcones
         * @param {*} qtd
         */ 
        function alterarQuantidadeIcones(qtd) {
            this.iconePlanejamento.quantidade = qtd;

            if (this.layerAtual) {
                var Icon = L.divIcon({
                    html: '<div class="planejamento-icone-wrapper" style="background-image: url(\'/assets/images/Pegmans/ic_pegman_' + this.iconePlanejamento.type + '_48px.svg\');"><b class="marker-cluster-counter">' + this.iconePlanejamento.quantidade + '</b></div>',
                    iconSize: [48, 48],
                });

                this.layerAtual.setIcon(Icon);
                this.layerAtual.options.quantidade = qtd;
            }
        }

        /**
         * 
         * @method  definirOpacidadePreenchimento
         * @param {*} opacidade 
         */
        function definirOpacidadePreenchimento(opacidade) {
            if (this.layerAtual && !this.layerAtual.options.icon) {
                this.layerAtual.setStyle({
                    fillOpacity: opacidade
                });
            }
        }

        /**
         * @method definirCorLinha
         * @param {*} cor 
         */
        function definirCorLinha(cor) {
            if (this.layerAtual && !this.layerAtual.options.icon) {
                this.layerAtual.setStyle({
                    color: cor
                });
            }
        }

        /**
         * @method definirEspessuraLinha
         * @param {*} espessura
         */
        function definirEspessuraLinha(espessura) {
            if (this.layerAtual && !this.layerAtual.options.icon) {
                this.layerAtual.setStyle({
                    weight: espessura
                });
            }
        }

        /**
         * @method definirOpacidadeLinha
         * @param {*} opacidade 
         */
        function definirOpacidadeLinha(opacidade) {
            if (this.layerAtual && !this.layerAtual.options.icon) {
                this.layerAtual.setStyle({
                    opacity: opacidade
                });
            }
        }

        /**
         * @method definirTexto
         * @param {*} texto 
         */
        function definirTexto(texto) {
            this.texto = texto;

            if (this.layerAtual) {
                if (texto) {
                    if (this.layerAtual.popup) {
                        this.layerAtual.popup
                            .setContent(this.texto);
                    } else {
                        this.layerAtual.popup = new L.Rrose({
                            width: 120,
                            offset: L.point(0, 0)
                        }).setContent(texto);
                        if (this.layerAtual instanceof L.Marker) {
                            this.layerAtual.popup.setLatLng(this.layerAtual.getLatLng());
                        } else {
                            this.layerAtual.popup.setLatLng(this.layerAtual.getBounds().getCenter());
                        }
                        this.layerAtual.popup.addTo(this.mapa);
                    }

                    this.layerAtual.options.texto = this.texto;
                    this.textChange();
                } else {
                    this.mapa.removeLayer(this.layerAtual.popup);
                    this.layerAtual.popup = null;
                }
            }

        }

        /**
         * @method _calcularPosicaoDesenho
         * @param {*} offsetX 
         * @param {*} offsetY 
         * @param {*} type 
         */
        function _calcularPosicaoDesenho(offsetX, offsetY, type) {

            var typeHash = {
                'polyline': 0,
                'polygon': 26,
                'rectangle': 52,
                'bombeiro': 78,
                'rota': 104
            };

            // Posição do mapa:
            var mapaPos = $('#mapaItem').offset();
            this.alturaCaixaDesenho.top = (mapaPos.top + offsetY + 32) + typeHash[type] + "px";
            this.alturaCaixaDesenho.left = (mapaPos.left + offsetX) + 30 + "px";
        }

        // Default: Bombeiro
        this.iconePlanejamento = {
            type: 'bombeiro',
            icon: icon,
            quantidade: 1
        };

        /**
         * @method definirAlturaCaixaDesenho
         * @param {*} altura 
         */
        function definirAlturaCaixaDesenho(altura) {
            var min = 160;
            this.alturaCaixaDesenho.top = (min + altura + 'px').toString();
        }

        /**
         * @method definirLayerAtual
         * @param {*} layer 
         * @param {*} mapa 
         */
        function definirLayerAtual(layer, mapa) {
            service.rotas = false;
            this.layerAtual = layer;
            this.layerAtual.desenhoPlanejamento = true;
            this.popup = null;
            this.mapa = mapa;
            // Ativando layer, se existir:
            this.layerAtual.on('click', function (e) {
                if (e.target.popup) {
                    e.target.popup.addTo(e.target._map);
                }

                triggerLayerChange(e);
            });
        }

        /**
         * @method triggerNovoLayer
         * @param {*} type 
         */
        function triggerNovoLayer(type) {
            service.state.isVisible = true;
            service.layerAtual = null;
            service.iconePlanejamento.quantidade = 1;
            service.newLayer(type);
        }

        /**
         * @method triggerLayerChange
         * @param {*} e 
         */
        function triggerLayerChange(e) {
            service.state.isVisible = true;
            service.layerAtual = e.target;
            service.layerChange(e);
        }

        /**
         * @method removerDesenho
         */
        function removerDesenho() {
            if (this.layerAtual && this.layerAtual._map) {
                if (this.layerAtual.popup) {
                    this.layerAtual._map.removeLayer(this.layerAtual.popup);
                }

                MapaService.removerDesenhoPlanejamento(this.layerAtual);
            } else if (service.rotas) {
                service.rotas = false;
                service.routesUpdated([]);
            }

            that.state.isVisible = false;
        }

        /**
         * @method on
         * @param {*} eventName 
         * @param {*} callback 
         */
        function on(eventName, callback) {
            return this.eventos[eventName].push(callback) - 1;
        }

        /**
         * @method unlisten
         * @param {*} eventName 
         * @param {*} index 
         */
        function unlisten(eventName, index) {
            // Zerando o callback:
            this.eventos[eventName][index] = angular.noop;
        }

        /**
         * @method clearListeners
         * @param {*} eventName 
         */
        function clearListeners(eventName) {
            this.eventos[eventName].length = 0;
        }

        /**
         * @method tracarRotas
         * @param {*} pontos 
         */
        function tracarRotas(pontos) {
            service.rotas = true;
            service.routesUpdated(pontos);
        }

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

            geocoder.geocode(query, function (response) {

                var enderecos = _.map(response, function (item) {
                    return {
                        endereco: item.name,
                        latitude: item.center.lat,
                        longitude: item.center.lng
                    }
                });

                deferred.resolve(enderecos);
            });

            return deferred.promise;
        }

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

            geocoder.reverse({
                lat: ponto.latitude,
                lng: ponto.longitude
            }, function (resposta) {
                deferred.resolve(resposta.name)
            });

            return deferred.promise;
        }


        var service = {
            state: this.state,
            texto: this.texto,
            rotas: false,
            removerDesenho: removerDesenho,
            calcularPosicaoDesenho: _calcularPosicaoDesenho,
            definirCorPreenchimento: definirCorPreenchimento,
            definirOpacidadePreenchimento: definirOpacidadePreenchimento,
            definirCorLinha: definirCorLinha,
            definirEspessuraLinha: definirEspessuraLinha,
            definirOpacidadeLinha: definirOpacidadeLinha,
            definirTexto: definirTexto,
            definirLayerAtual: definirLayerAtual,
            triggerNovoLayer: triggerNovoLayer,
            triggerLayerChange: triggerLayerChange,
            definirAlturaCaixaDesenho: definirAlturaCaixaDesenho,
            on: on,
            unlisten: unlisten,
            clearListeners: clearListeners,
            alturaCaixaDesenho: this.alturaCaixaDesenho,
            iconePlanejamento: this.iconePlanejamento,
            alterarQuantidadeIcones: alterarQuantidadeIcones,
            tracarRotas: tracarRotas,
            buscarEnderecos: buscarEnderecos,
            buscarEnderecoDeCoordenada: buscarEnderecoDeCoordenada,
            newLayer: function (x) {
                this.eventos.newLayer.forEach(function (cb) {
                    cb(x);
                });
            },
            layerChange: function (x) {
                this.eventos.layerChange.forEach(function (cb) {
                    cb(x);
                });
            },
            textChange: function (x) {
                this.eventos.textChange.forEach(function (cb) {
                    cb(x);
                });
            },
            iconChange: function (x) {
                console.log(this.eventos.iconChange);
                this.eventos.iconChange.forEach(function (cb) {
                    cb(x);
                });
            },
            routesUpdated: function (x) {
                this.eventos.routesUpdated.forEach(function (cb) {
                    cb(x);
                });
            },
            mapRoutesUpdated: function (x) {
                this.eventos.mapRoutesUpdated.forEach(function (cb) {
                    cb(x);
                });
            },
            eventos: {
                'iconChange': [],
                'textChange': [],
                'layerChange': [],
                'newLayer': [],
                'routesUpdated': [],
                'mapRoutesUpdated': []
            }
        }

        return service;
    }

})();