(function () {
    'use strict';

    angular
        .module('setoresApp')
        .directive('edicaoApontamentos', edicaoApontamentos);

    edicaoApontamentos.$inject = ['__env', '$location', 'setoresServiceFactory', 'mapsSingletonService', '$timeout',
        'ngNotify', 'edicaoApontamentosFormHelpersFactory', 'utilsFactory', 'VeiculoEdicao',
        'ViagemVeiculoEdicao', 'ApontamentoVeiculoEdicao', 'MotoristaEdicao'];

    /* @ngInject */
    function edicaoApontamentos(__env, $location, setoresServiceFactory, mapsSingletonService, $timeout,
                                ngNotify, edicaoApontamentosFormHelpersFactory, utilsFactory, VeiculoEdicao,
                                ViagemVeiculoEdicao, ApontamentoVeiculoEdicao, MotoristaEdicao) {

        return {
            link: link,
            restrict: 'A',
            replace: false,
            scope: false
        };

        function link(scope) {
            let _urlParams = $location.$$search;
            let _validacaoForms = [];
            let _form = {};

            const _horarioAgendaSetor = {
                inicio: new Date(_urlParams.dt),
                fim: new Date(_urlParams.dt),
            };

            angular.extend(scope.vm, {
                abrirModalEdicaoApontamentos: abrirModalEdicaoApontamentos,
                fecharModalEdicaoApontamentos: fecharModalEdicaoApontamentos,
                incluirVeiculoEdicaoApontamentos: incluirVeiculo,
                removerVeiculoEdicaoApontamentos: removerVeiculo,
                incluirViagemEdicaoApontamentos: incluirViagem,
                removerViagemEdicaoApontamentos: removerViagem,
                estiloValidacoesCampos: estiloValidacoesCampos,
                alternarVisibilidadeRastreamento: alternarVisibilidadeRastreamento,
                validarEdicaoServidor: validarEdicaoServidor
            });

            function abrirModalEdicaoApontamentos() {
                scope.vm.showLoading();
                scope.vm.veiculoEmVinculacao = false;
                scope.vm.listaVeiculosEdicao = [];
                scope.vm.listaVeiculosInclusao = [];
                scope.vm.listaMotoristas = [];

                utilsFactory.changeTimeFromDate(_horarioAgendaSetor.inicio, scope.vm.horarioAgendaSetor.inicio);
                utilsFactory.changeTimeFromDate(_horarioAgendaSetor.fim, scope.vm.horarioAgendaSetor.fim);

                setoresServiceFactory.carregarMotoristas().then(result =>
                    scope.vm.listaMotoristas = result.data.map(motorista => new MotoristaEdicao(motorista.Nome, motorista.Matricula)));

                setoresServiceFactory.carregarVeiculosViagemPorData(_urlParams.codigoSetor, _urlParams.dt).then((result) => {
                    formatarRetornoServidor(result.data).forEach(veiculo => {
                        if (veiculo.codigoSetor === parseInt(_urlParams.codigoSetor)) {
                            scope.vm.listaVeiculosEdicao.push(veiculo);
                        } else {
                            scope.vm.listaVeiculosInclusao.push(veiculo);
                        }
                    });

                    scope.vm.openModal('Edição de apontamentos',
                        `${__env.appPath}scripts/components/edicao-apontamentos/edicao-apontamentos.html`, fecharModalEdicaoApontamentos, true)
                        .then(() => {
                            _form = scope.vm.formEditarApontamentos;

                            $timeout(() => {
                                _form.$$element.on('submit', () =>
                                    _validacaoForms.forEach(form => edicaoApontamentosFormHelpersFactory.revalidarFormulario(form)));

                                _form.$$controls.forEach((formGroup, idx) => {
                                    edicaoApontamentosFormHelpersFactory
                                        .adicionarValidacao(_form, _validacaoForms, idx);
                                });
                                scope.vm.hideLoading();
                            }, 500);
                        });
                });
            }

            function fecharModalEdicaoApontamentos() {
                scope.vm.closeModal()
                    .then(() => {
                        scope.vm.tipoErroApontamento = null;

                        scope.vm.listaVeiculosEdicao
                            .forEach(veiculo => veiculo.ocultarHistoricosVisiveis());

                        scope.vm.veiculoEmVinculacao = false;
                        _validacaoForms = [];
                        scope.vm.listaVeiculosEdicao = [];
                        scope.vm.listaVeiculosInclusao = [];
                        scope.vm.listaMotoristas = [];
                    });
            }

            function incluirVeiculo(veiculoUuid) {
                const idx = scope.vm.listaVeiculosInclusao.findIndex(veiculo => veiculo.uuid === veiculoUuid);

                scope.vm.listaVeiculosEdicao.push(scope.vm.listaVeiculosInclusao.splice(idx, 1)[0]);
                scope.vm.veiculoEmVinculacao = false;

                let novoIdx = scope.vm.listaVeiculosEdicao.length - 1;

                edicaoApontamentosFormHelpersFactory
                    .adicionarValidacao(_form, _validacaoForms, novoIdx)
                    .then(() => {
                        let veiculoSelecionado = scope.vm.listaVeiculosEdicao[novoIdx];

                        if (veiculoSelecionado.viagens.length === 0) {
                            incluirViagem(veiculoSelecionado);
                            veiculoSelecionado.possuiViagensOriginais = false;
                        }
                    });
            }

            function removerVeiculo(veiculoUuid) {
                const idx = scope.vm.listaVeiculosEdicao.findIndex(veiculo => veiculo.uuid === veiculoUuid);

                scope.vm.listaVeiculosEdicao[idx].ocultarHistoricosVisiveis();
                scope.vm.listaVeiculosInclusao.push(scope.vm.listaVeiculosEdicao.splice(idx, 1)[0]);

                edicaoApontamentosFormHelpersFactory
                    .removerValidacao(_validacaoForms, veiculoUuid);
            }

            function incluirViagem(veiculo) {
                const ultimaViagem = veiculo.viagens[veiculo.viagens.length - 1];
                const ultimoApontamento = ultimaViagem ? ultimaViagem.apontamentos[ultimaViagem.apontamentos.length - 1] : null;

                const apontamentos = [
                    new ApontamentoVeiculoEdicao(null, 12,
                        ultimoApontamento ? utilsFactory.addMinutesToDate(ultimoApontamento.data, 1) : _horarioAgendaSetor.inicio),

                    new ApontamentoVeiculoEdicao(null, 13,
                        ultimoApontamento ? utilsFactory.addHoursToDate(ultimoApontamento.data, 1) : _horarioAgendaSetor.fim)
                ];

                veiculo.viagens.push(new ViagemVeiculoEdicao(veiculo.codigoSetor, veiculo.codigoSetorRealizado, apontamentos));

                edicaoApontamentosFormHelpersFactory
                    .redefinirValidacao(_validacaoForms, veiculo.uuid);
            }

            function removerViagem(veiculo, viagemUuid) {
                veiculo.viagens.find(viagem => viagem.uuid === viagemUuid).ocultarHistoricoRastreamento();
                veiculo.viagens = veiculo.viagens.filter(viagem => viagem.uuid !== viagemUuid);

                edicaoApontamentosFormHelpersFactory
                    .redefinirValidacao(_validacaoForms, veiculo.uuid);
            }

            function estiloValidacoesCampos(uuidVeiculo, indiceViagem, indiceApontamento) {
                let formGroup = scope.vm.formEditarApontamentos.$$controls
                    .find(form => form.$$element.data('uuid').includes(uuidVeiculo));

                let validation = formGroup.$$controls
                    .find(control => control.$name === 'viagem-[' + indiceViagem + '].apontamento-[' + indiceApontamento + ']')
                    .customValidation;

                if (validation === undefined) {
                    return true;
                }

                return validation;
            }

            function alternarVisibilidadeRastreamento(veiculo, viagem) {
                if (viagem.visibilidadeRastreamento) {
                    viagem.ocultarHistoricoRastreamento();
                    return;
                }

                setoresServiceFactory.buscarHistoricoPorVeiculo(veiculo.codigo,
                    viagem.apontamentos.find(apontamento => apontamento.tipo === 12).data.toJSON(),
                    viagem.apontamentos.find(apontamento => apontamento.tipo === 13).data.toJSON())
                    .then(result => {
                        if (result.data.length === 0) {
                            exibirMensagemFeedbackNaModal('Não existem informações de rastreamento para o período informado', 'warn');
                            return;
                        }

                        viagem.historicoRastreamento = result.data
                            .map(ponto => new PontoHistoricoVeiculoEdicao(ponto.Codigo, ponto.DataHora, ponto.Latitude, ponto.Longitude));

                        viagem.mostrarHistoricoRastreamento();
                        mapsSingletonService.getMap().fitBoundsPolylines('viagemVeiculoEdicao');
                    });
            }

            function exibirMensagemFeedbackNaModal(msg, tipo) {
                document.getElementsByClassName('modal-edicao-apontamentos-content')[0].scrollTop = 0;

                ngNotify.set(msg, { target: '#modalNotificationOuter', type: tipo, sticky: false, button: true });
            }

            function formatarRetornoServidor(dados) {
                dados = utilsFactory.convertKeysToCamelCase(dados);

                return dados.map((veiculo) =>
                    new VeiculoEdicao(veiculo.codigoVeiculo, veiculo.identificador, veiculo.codigoSetor, veiculo.codigoSetorRealizado, veiculo.setor, veiculo.viagens || []));
            }

            function validarEdicaoServidor() {
                let envioParaValidacao = edicaoApontamentosFormHelpersFactory
                    .formatarDadosValidacaoServidor(_urlParams.codigoSetor, scope.vm.listaVeiculosEdicao);

                scope.vm.setFormStatus(_form, 'SENDING');

                setoresServiceFactory.validarDadosEdicaoApontamentos(envioParaValidacao)
                    .then(result => {
                        scope.vm.setFormStatus(_form, null);
                        let setoresAfetados = result.data.filter(setores => setores.Codigo !== parseInt(_urlParams.codigoSetor))
                            .map(s => `<li>${s.Descricao}</li>`).join('');

                        if (setoresAfetados) {
                            scope.vm.animatePromptIn('Setores afetados',
                                `<span>Atenção, o(s) seguinte(s) setor(es) será(ão) afetados pelo reprocessamento:</span> <ul class="lista-setores-afetados">${setoresAfetados}</ul>`,
                                'Reprocessar', editarApontamentos);
                        } else {
                            editarApontamentos();
                        }
                    })
                    .catch((error) => {
                        scope.vm.setFormStatus(_form, 'SEND_FAIL').then(() => {
                            scope.vm.animatePromptOut();
                            exibirMensagemFeedbackNaModal('Não foi possível realizar esta operação', 'error');
                            $timeout(() => scope.vm.setFormStatus(_form, null), 1000);
                        });
                    });
            }

            function editarApontamentos() {
                if (scope.vm.promotIsOpen) {
                    scope.vm.animatePromptOut();
                }

                let envioParaReprocessamento = edicaoApontamentosFormHelpersFactory
                    .formatarDadosReprocessamentoServidor(parseInt(_urlParams.codigoSetor), new Date(_urlParams.dt), scope.vm.listaVeiculosEdicao);

                scope.vm.setFormStatus(_form, 'SENDING');

                setoresServiceFactory.reprocessarSetores(envioParaReprocessamento).then(result => {
                    if (!result.data.IsSucesso) {
                        console.error(result.data.Resposta);
                        throw new Error;
                    }

                    scope.vm.setFormStatus(_form, 'SEND_SUCCESS').then(() => {
                        fecharModalEdicaoApontamentos();
                        scope.vm.tabActive = 'pendentes';

                        ngNotify.set('As informações do setor serão reprocessadas de acordo com as alterações de apontamentos', {
                            type: 'success',
                            sticky: true
                        });

                        $timeout(() => {
                            scope.vm.inicializarControllerDetalhes();
                        }, 5000);
                    });
                }).catch((error) => {
                    scope.vm.setFormStatus(_form, 'SEND_FAIL').then(() => {
                        exibirMensagemFeedbackNaModal('Não foi possível realizar esta operação', 'error');
                        $timeout(() => scope.vm.setFormStatus(_form, null), 1000);
                    });
                });

            }
        }
    }
})();
