class PlanejamentoHistorico {
    constructor(viewModel) {
        this.InfoWindows = [];
        this.viewModel = viewModel;
        this.PolylineHistoricoId = ko.observable("polylineHistorico");
        this.PlotarHistorico();
    }

    PlotarHistorico(data) {
        this.Destroy();
        const mSelf = this;

        if (data) {
            this.viewModel = data;
        }

        if (this.viewModel.PontosParada) {
            const pontosP = this.viewModel.PontosParada();
            const pontosAgrupados = {};
            for (let i in pontosP) {
                const ponto = pontosP[i];
                const key = `${ponto.Latitude()}_${ponto.Longitude()}`;
                pontosAgrupados[key] = pontosAgrupados[key] || [];
                pontosAgrupados[key].push(ponto);
            }

            for (let x in pontosAgrupados) {
                mSelf.AdicionarMarker(`${this.PolylineHistoricoId()}PontoParada${x}`, pontosAgrupados[x],
                    this.viewModel.PathImgPontoParada());
            }
        }

        mSelf.AdicionarPolyline(this.PolylineHistoricoId(), this.viewModel.Lista(), true, '#FF0000', true);
    }

    AdicionarMarker(id, ponto, icone) {
        const mSelf = this;
        const options = new InlogMaps.MarkerOptions([ponto[0].Latitude(), ponto[0].Longitude()], true);
        options.icon = new InlogMaps.MarkerIcon(icone);
        options.object = id;

        vm.currentMap.drawMarker('markersHistorico', options, (event, id) => {
            const popupOptions = new InlogMaps.PopupOptions();
            popupOptions.content = mSelf.MontarInfoWindowPontoParada(ponto.map(x => x.InfoWindow));
            popupOptions.marker = 'markersHistorico';
            popupOptions.conditionMarker = (item) => item === id;

            vm.currentMap.drawPopup('pontoParada', popupOptions);
        });
    }

    AdicionarPolyline(id, latLngArray, addToMap, cor, fitBounds) {
        const pts = [];
        let latLng = null;

        for (let j = 0; j < latLngArray.length; j++) {
            if (latLngArray[j].Latitude() < -90 || latLngArray[j].Latitude() > 90) {
                latLng = [latLngArray[j].Latitude() / 1000000, latLngArray[j].Longitude() / 1000000];
            }
            else latLng = [latLngArray[j].Latitude(), latLngArray[j].Longitude()];

            pts.push(latLng);
            this.InfoWindows.push(this.MontarInfoWindow(latLngArray[j].InfoWindow));
        }

        const options = new InlogMaps.PolylineOptions(pts, addToMap, fitBounds);
        options.color = cor;
        options.infowindows = this.InfoWindows;
        options.object = id;
        options.zIndex = 2;
        options.navigateOptions = new InlogMaps.NavigationOptions('#000000', 5, false);
        vm.currentMap.drawPolylineWithNavigation('polylineHistorico', options);
    }

    MontarInfoWindow(infoWindow) {
        const elemento = $("#tpl-infoWindow").html()
            .replace("{DataHora}", infoWindow.DataHora())
            .replace("{Velocidade}", infoWindow.Velocidade())
            .replace("{Distancia}", infoWindow.Distancia())
            .replace("{Tempo}", infoWindow.Duracao());

        return elemento;
    }

    MontarInfoWindowPontoParada(infoWindowList) {
        let listaPonto;
        infoWindowList.forEach((infoWindow, index) => {
            const title = infoWindowList.length > 1 ? 'Pontos de parada' : 'Ponto de parada';

            const elemento = $("#tpl-infoWindowPontoParada").html()
                .replace("{Titulo}", index === 0 ? title : '')
                .replace("{Separador}", index === 0 ? '<br /> <br />' : '<br />')
                .replace("{DataHoraInicio}", infoWindow.DataHoraInicio())
                .replace("{DataHoraFim}", infoWindow.DataHoraFim())
                .replace("{Tempo}", infoWindow.TempoParado());

            if (!listaPonto) {
                listaPonto = elemento;
            }
            else listaPonto = listaPonto.concat(elemento);
        });

        return listaPonto;
    }

    Destroy() {
        this.InfoWindows = [];
        vm.currentMap.removePolylines('polylineHistorico');
        vm.currentMap.closePopup('pontoParada');
        vm.currentMap.removeMarkers('markersHistorico');
        this.LimparPolyline('polylineInicio');
        this.LimparPolyline('polylineFim');
        this.LimparPolylinesHighlight();
    }

    FocarPosicaoMapa(index, limparInfoWindow) {
        if (index !== null) {
            vm.currentMap.setIndexPolylineHighlight('polylineHistorico', parseInt(index));
        }
        else vm.currentMap.fitBoundsPolylines('polylineHistorico');

        if (limparInfoWindow) {
            vm.currentMap.removePolylineHighlight();
        }
    }

    FiltrarPorVelocidade(posicoes, velocidadeInicial, velocidadeFinal) {
        for (let x in posicoes) {
            if (posicoes[x].Velocidade() >= velocidadeInicial && posicoes[x].Velocidade() <= velocidadeFinal) {
                /* X é a ultima posição, por isso é reduzido um, para poder passar o ponto inicial como parâmetro */
                this.SelecionarPosicao('pontosVelocidade', posicoes, parseInt(x) - 1, false);
            }
        }
    }

    FiltrarPontosParada(listaPontosParada, tempoParametro, tipoFiltro) {
        vm.currentMap.closePopup('pontoParada');

        if (tipoFiltro === 'maior') {
            listaPontosParada.sort((a, b) => a.TempoParado() > b.TempoParado() ? 1 : -1);
        } else {
            listaPontosParada.sort((a, b) => a.TempoParado() > b.TempoParado() ? -1 : 1);
        }

        for (let x in listaPontosParada) {
            const pontoParada = listaPontosParada[x];
            const markerId = `${this.PolylineHistoricoId()}PontoParada${pontoParada.Latitude()}_${pontoParada.Longitude()}`;

            if (tipoFiltro == "maior") {
                if (pontoParada.TempoParado() <= tempoParametro) {
                    vm.currentMap.toggleMarkers(false, 'markersHistorico', (id) => id === markerId);
                }
                else vm.currentMap.toggleMarkers(true, 'markersHistorico', (id) => id === markerId);
            }
            else {
                if (pontoParada.TempoParado() >= tempoParametro) {
                    vm.currentMap.toggleMarkers(false, 'markersHistorico', (id) => id === markerId);
                }
                else vm.currentMap.toggleMarkers(true, 'markersHistorico', (id) => id === markerId);
            }
        }
    }

    MostrarPontosParada(lista) {
        if (lista) {
            lista.forEach(ponto => vm.currentMap.toggleMarkers(true, 'markersHistorico',
                (id) => id === `${this.PolylineHistoricoId()}PontoParada${ponto.Latitude()}_${ponto.Longitude()}`));
        }
    }

    SelecionarPosicao(tipo, posicoes, index, drawPopup = true) {
        /* Se o index for maior, vamos selecionar o ultimo ponto */
        if (index > posicoes.length - 1) {
            index = posicoes.length - 2;
        }
        else if (index < 0) index = 0;

        const pontoFinal = [posicoes[index + 1].Latitude(), posicoes[index + 1].Longitude()];
        const path = [[posicoes[index].Latitude(), posicoes[index].Longitude()], pontoFinal];
        const options = new InlogMaps.PolylineOptions(path, true);
        options.color = '#000000';
        options.weight = 5;
        options.zIndex = 3;
        vm.currentMap.drawPolyline(tipo, options);

        if (drawPopup) {
            const popupOptions = new InlogMaps.PopupOptions(pontoFinal, this.InfoWindows[index])
            vm.currentMap.drawPopup(tipo, popupOptions);
        }
    }

    LimparPolylinesHighlight() {
        vm.currentMap.removePolylineHighlight();
        this.LimparPolyline('pontosVelocidade');
    }

    LimparPolyline(tipo) {
        vm.currentMap.closePopup(tipo);
        vm.currentMap.removePolylines(tipo);
    }

    AlterarIconePolylinha(sentidoSelecionado) {
        const type = 'polylineHistorico';

        if (vm.currentMap.polylineExists(type)) {
            let options = new InlogMaps.PolylineOptions();

            if (sentidoSelecionado) {
                options.style = InlogMaps.PolylineType.Arrow;
            }

            vm.currentMap.alterPolylineOptions(type, options)
        }
    }
}





















