function FerramentaNovoFiltroVeiculosViewModel(data) {
    const mSelf = this;
    mSelf.Data = ko.observable(new FerramentaNovoFiltroVeiculos(data.Data));
    mSelf.FerramentaId = data.FerramentaId;
    mSelf.Template = data.Template;
    mSelf.Visivel = ko.observable(true);
    mSelf.Icone = data.Icone;
    mSelf.Nome = data.Nome;
    mSelf.Ordem = 6;
    mSelf.Titulo = data.Titulo;
    mSelf.NomeBotao = data.NomeBotao;

    mSelf.Init = () => mSelf.Data().Init();
}

function FerramentaNovoFiltroVeiculos(data) {
    const mSelf = this;

    /* Planejamento linhas */
    ko.utils.arrayForEach(data(), (item) => item.Carregado = ko.observable(false));
    mSelf.Data = data;
    mSelf.ListaFiltrada = ko.observableArray([]);
    mSelf.Planejamentos = {};

    mSelf.Veiculos;
    mSelf.VeiculosFiltrados;
    mSelf.ModuloGridVeiculos;

    /* itens de filtro */
    mSelf.ListaTipoVeiculo = ko.observableArray([]);
    mSelf.ListaLinhas = ko.observableArray([]);
    mSelf.ListaOperacoes = ko.observableArray([]);
    mSelf.ListaIdentificadorVeiculos = ko.observableArray([]);
    mSelf.ListaDescricaoVeiculos = ko.observableArray([]);
    mSelf.ListaPlacas = ko.observableArray([]);
    mSelf.ListaNumerosSerie = ko.observableArray([]);
    mSelf.ListaGrupoControle = ko.observableArray([]);
    mSelf.Identificador = ko.observable();
    mSelf.Veiculo = ko.observable();
    mSelf.Placa = ko.observable();
    mSelf.NumeroSerie = ko.observable();
    mSelf.AvlConectado = ko.observable(false);
    mSelf.AvlDesconectado = ko.observable(false);
    mSelf.IgnicaoLigado = ko.observable(false);
    mSelf.IgnicaoDesligado = ko.observable(false);
    mSelf.PesquisarLinha = ko.observable();
    mSelf.VerPlanejamentosFiltrados = ko.observable(false);

    /* filtro data hora */
    mSelf.DataHoraCheckMaiorQue = ko.observable('Maior');
    mSelf.DataSelecionada = ko.observable(null);
    mSelf.HoraSelecionada = ko.observable(null);
    mSelf.CodigoLinhasFiltradas = ko.observableArray([]);

    mSelf.Init = () => {
        mSelf.ModuloGridVeiculos = vm.GetModulo('GridVeiculosViewModel');

        ko.utils.arrayForEach(mSelf.ModuloGridVeiculos.VeiculosFiltrados(), (item) => {
            if (item.OperacoesVinculadasVeiculo().length >= 1) {
                item.DescricaoOperacao(item.OperacoesVinculadasVeiculo().map(x => x.DescricaoOperacao()));
            }
            else item.DescricaoOperacao('SEM OPERAÇÂO');

            if (item.GrupoControle().length >= 1) {
                item.DescricaoGrupoControle(item.GrupoControle().map(x => x.DescricaoGrupoControle()));
            }
            else item.DescricaoGrupoControle('SEM GRUPO DE CONTROLE');
        });

        mSelf.Veiculos = ko.observableArray(mSelf.ModuloGridVeiculos.VeiculosGrid());
        mSelf.VeiculosFiltrados = ko.observableArray(mSelf.ModuloGridVeiculos.VeiculosFiltrados());
        mSelf.CarregaFiltros();

        $('#filtroVeiculos').filtroDDS(mSelf.EventoFiltroDDS);
    };

    mSelf.EventoFiltroDDS = (elemento) => {
        if (elemento[0] != undefined) {
            const item = elemento.attr('data-item');
            $('#checkbox-' + item).attr('checked', false);

            switch (item) {
                case 'item-1':
                    mSelf.LimparListaSelecionado('ListaTipoVeiculo');
                    break;
                case 'item-2':
                    mSelf.Identificador('');
                    mSelf.LimparListaSelecionado('ListaIdentificadorVeiculos');
                    break;
                case 'item-3':
                    mSelf.Veiculo('');
                    mSelf.LimparListaSelecionado('ListaDescricaoVeiculos');
                    break;
                case 'item-4':
                    mSelf.Placa('');
                    mSelf.LimparListaSelecionado('ListaPlacas');
                    break;
                case 'item-5':
                    mSelf.NumeroSerie('');
                    mSelf.LimparListaSelecionado('ListaNumerosSerie');
                    break;
                case 'item-7':
                    mSelf.LimparListaSelecionado('ListaOperacoes');
                    break;
                case 'item-8':
                    mSelf.AvlConectado(false);
                    mSelf.AvlDesconectado(false);
                    break;
                case 'item-9':
                    mSelf.IgnicaoLigado(false);
                    mSelf.IgnicaoDesligado(false);
                    break;
                case 'item-10':
                    mSelf.DataSelecionada('');
                    mSelf.HoraSelecionada('');

                    break;
                case 'item-11':
                    mSelf.LimparListaSelecionado('ListaGrupoControle');
                    break;
                default:
                    break;
            }
            mSelf.EventoFiltroDDS(elemento.next());
        }
        return;
    };

    class ClassListaItem {
        constructor() {
            this.ListaTipoVeiculo = ko.observable(0);
            this.ListaLinhas = ko.observable(0);
            this.ListaOperacoes = ko.observable(0);
            this.ListaIdentificadorVeiculos = ko.observable(0);
            this.ListaDescricaoVeiculos = ko.observable(0);
            this.ListaPlacas = ko.observable(0);
            this.ListaNumerosSerie = ko.observable(0);
            this.ListaAvl = ko.observable(0);
            this.ListaIgnicao = ko.observable(0);
            this.ListaGrupoControle = ko.observable(0);
        }
    }

    mSelf.CountListaItem = ko.observable(new ClassListaItem());

    mSelf.ChangeItemSelecionado = (lista, data, event) => {
        let item = mSelf.CountListaItem()[lista];

        if (event.target.checked) {
            item(item() + 1);
        }
        else item(item() - 1);

        if (item() == 0) {
            const elemento = $('#filtro-' + event.target.parentNode.parentNode.parentNode.className).next();
            mSelf.EventoFiltroDDS(elemento);
        }

        $('#btnFiltrar').prop('disabled', false);
    };

    mSelf.CarregaFiltros = (limpar) => {
        mSelf.ListaTipoVeiculo(mSelf.GetDistinctValues('TipoVeiculo', 'ListaTipoVeiculo', limpar));
        mSelf.ListaOperacoes(mSelf.GetDistinctValues('DescricaoOperacao', 'ListaOperacoes', limpar, true));
        mSelf.ListaIdentificadorVeiculos(mSelf.GetDistinctValues('Identificador', 'ListaIdentificadorVeiculos', limpar));
        mSelf.ListaDescricaoVeiculos(mSelf.GetDistinctValues('Descricao', 'ListaDescricaoVeiculos', limpar));
        mSelf.ListaPlacas(mSelf.GetDistinctValues('Placa', 'ListaPlacas', limpar));
        mSelf.ListaNumerosSerie(mSelf.GetDistinctValues('NumeroSerie', 'ListaNumerosSerie', limpar));
        mSelf.ListaGrupoControle(mSelf.GetDistinctValues('DescricaoGrupoControle', 'ListaGrupoControle', limpar, true));
    };

    mSelf.AutoCompletGenerico = (campo, nomeLista) => {
        ko.utils.arrayForEach(mSelf[nomeLista](), (row) => {
            if (row.Item != null) {
                if (row.Item.toUpperCase().indexOf(mSelf[campo]().toUpperCase()) > -1) {
                    row.Visivel(true);
                    return;
                }
            }
            row.Visivel(false);
        });
    };

    mSelf.GetDistinctValues = (coluna, lista, limpar, contemSubListas = false) => {
        if (limpar != null && limpar)
            mSelf[lista].removeAll();

        class ListItens {
            constructor(valor) {
                this.Item = valor;
                this.Visivel = ko.observable(true);
                const IsSelecionado = ko.utils.arrayFilter(mSelf[lista](), (item) => item.Selecionado() === true && item.Item === valor);
                if (IsSelecionado.length > 0) {
                    this.Selecionado = ko.observable(true);
                }
                else this.Selecionado = ko.observable(false);
            }
        }

        const veiculosFiltrados = mSelf.VeiculosFiltrados();
        const col = ko.utils.arrayMap(veiculosFiltrados, (item) => item[coluna]());
        const distinct = (value, index, self) => self.indexOf(value) === index;
        const sort = (contemSubListas ? col.flatMap(x => x) : col).filter(distinct).sort();

        return ko.utils.arrayMap(sort, (item) => new ListItens(item));
    };

    mSelf.LimparFiltros = () => {
        $('.loading-inlog').fadeIn('fast', () => {
            mSelf.VeiculosFiltrados(mSelf.Veiculos());
            mSelf.ModuloGridVeiculos.AtualizarGridFiltrado(mSelf.VeiculosFiltrados());

            mSelf.Identificador('');
            mSelf.Veiculo('');
            mSelf.Placa('');
            mSelf.NumeroSerie('');
            mSelf.DataSelecionada('');
            mSelf.HoraSelecionada('');

            mSelf.CarregaFiltros(true);

            vm.currentMap.toggleMarkers(true, 'veiculos');
            vm.currentMap.refreshClusterer('veiculos');
            mSelf.VerPlanejamentosFiltrados(false);

            ko.utils.arrayForEach(mSelf.Veiculos(), (v) => {
                if (!v.Visivel()) {
                    v.Visivel(true);
                }
            });

            const modulo = vm.GetModulo('GridVeiculosViewModel');
            if (modulo) {
                modulo.TotalVeiculos = modulo.Data.VeiculosGrid().length;
                modulo.TotalVeiculosMapa = modulo.ItensPlotados;
                modulo.AlterarTituloGrid();
            }

            const config = vm.GetFerramenta('ConfiguracoesVeiculos');
            if (config) {
                config.Data().setarConfiguracoesMapa();
            }

            $('#filtroVeiculos').filtroDDS(mSelf.EventoFiltroDDS);

            /* após limpar os filtros da Grid, marcar os veículos que já estavam selecionados */
            if (modulo) {
                modulo.Data.MarcarVeiculosSelecionados();
            }

            $('#btnFiltrar').prop('disabled', false);
            $('.loading-inlog').fadeOut();
        });
    };

    mSelf.FiltrarVeiculos = () => {
        $('.loading-inlog').fadeIn('fast', () => {
            mSelf.VeiculosFiltrados(mSelf.Veiculos());

            const lstColunaSelecao = mSelf.RecuperaFiltroSelecionandos();
            ko.utils.arrayForEach(lstColunaSelecao, (itemFiltro) => mSelf.aplicarFiltroGrid(itemFiltro));
            mSelf.ModuloGridVeiculos.AtualizarGridFiltrado(mSelf.VeiculosFiltrados());

            if (mSelf.VeiculosFiltrados().length > 0) {
                mSelf.CarregaFiltros();
            }

            const modulo = vm.GetModulo('GridVeiculosViewModel');
            if (modulo) {
                vm.currentMap.clearMarkersClusterer('veiculos');
                vm.currentMap.toggleMarkers(false, 'veiculos');

                ko.utils.arrayForEach(mSelf.VeiculosFiltrados(),
                    (veiculo) => mSelf.SetarMarkerVeiculo(veiculo, true));

                modulo.TotalVeiculosMapa = vm.currentMap.countMarkers('veiculos');
                modulo.TotalVeiculos = modulo.TotalVeiculosMapa;
                modulo.AlterarTituloGrid();
                vm.currentMap.refreshClusterer('veiculos');
            }

            $('#filtrarVeiculos').filtroDDS(mSelf.EventoFiltroDDS);
            mSelf.VerPlanejamentosFiltrados(true);

            /* após filtrar os veiculos, marcar os veículos que já estavam selecionados */
            if (modulo) {
                modulo.Data.MarcarVeiculosSelecionados();
            }

            $('#btnFiltrar').prop('disabled', true);
            $('.menu_bloco').hide();
            $('.loading-inlog').fadeOut();
        });
    };

    mSelf.LimparListaSelecionado = (nomeLista) =>
        ko.utils.arrayForEach(mSelf[nomeLista](), (item) => item.Selecionado(false));

    mSelf.SelecionarTodos = (nomeLista, data, evt) => {
        ko.utils.arrayForEach(mSelf[nomeLista](), (item) => {
            if (evt.target.checked && item.Visivel()) {
                item.Selecionado(true);
            }
            else item.Selecionado(false);
        });

        if (evt.target.checked) {
            mSelf.CountListaItem()[nomeLista](mSelf[nomeLista]().length);
        } else {
            const elemento = $('#filtro-' + evt.target.parentNode.parentNode.parentNode.className).next();
            mSelf.CountListaItem()[nomeLista](0);
            mSelf.EventoFiltroDDS(elemento);
        }

        $('#btnFiltrar').prop('disabled', false);
    };

    mSelf.SelecionaTodosCheck = (campo1, campo2, data, evt) => {
        if (evt.target.checked) {
            mSelf[campo1](true);
            mSelf[campo2](true);
        }
        else {
            mSelf[campo1](false);
            mSelf[campo2](false);
        }
    };

    mSelf.RecuperaFiltroSelecionandos = () => {
        const itens = $('.lista-b li');
        const filtros = [];

        ko.utils.arrayForEach(itens, (item) => filtros.push(item.attributes['data-item'].value));

        return filtros;
    };

    mSelf.aplicarFiltroGrid = (filtro) => {
        let resultado = [];
        let lista = [];

        if ($('#filtro-' + filtro).attr('class') == 'desativado')
            return;

        switch (filtro) {
            case 'item-1':
                resultado = mSelf.FiltroArrayGenerico('TipoVeiculo', mSelf.ListaTipoVeiculo());
                break;
            case 'item-2':
                resultado = mSelf.FiltroArrayGenerico('Identificador', mSelf.ListaIdentificadorVeiculos());
                break;
            case 'item-3':
                resultado = mSelf.FiltroArrayGenerico('Descricao', mSelf.ListaDescricaoVeiculos());
                break;
            case 'item-4':
                resultado = mSelf.FiltroArrayGenerico('Placa', mSelf.ListaPlacas());
                break;
            case 'item-5':
                resultado = mSelf.FiltroArrayGenerico('NumeroSerie', mSelf.ListaNumerosSerie());
                break;
            case 'item-7':
                resultado = mSelf.FiltroMultiOperacoes('DescricaoOperacao', mSelf.ListaOperacoes());
                break;
            case 'item-8':
                lista = [];
                if (mSelf.AvlConectado())
                    lista.push('T');
                if (mSelf.AvlDesconectado())
                    lista.push('F');
                resultado = mSelf.FiltroBooleano('Conectado', lista);
                break;
            case 'item-9':
                lista = [];
                if (mSelf.IgnicaoLigado()) {
                    lista.push('Ligada');
                }

                if (mSelf.IgnicaoDesligado()) {
                    lista.push('Desligada');
                }

                resultado = mSelf.FiltroBooleano('StatusIgnicao', lista);
                break;
            case 'item-10':
                resultado = mSelf.FiltroDataHora(mSelf.DataHoraCheckMaiorQue());
                break;
            case 'item-11':
                resultado = mSelf.FiltroMultiGrupoControle('DescricaoGrupoControle', mSelf.ListaGrupoControle());
                break;
            default:
                break;
        }
        if (resultado != null) {
            mSelf.VeiculosFiltrados(resultado);
        }
    };

    mSelf.FiltroBooleano = (campo, lista) => {
        if (lista.length <= 0) {
            return mSelf.VeiculosFiltrados();
        }

        return $.grep(mSelf.VeiculosFiltrados(), (veic) => $.inArray(veic[campo](), lista) > -1);
    };

    mSelf.FiltroArrayGenerico = (campo, lista) => {
        const tiposSelecionados = ko.utils.arrayFilter(lista, (item) => item.Selecionado() === true);
        const tipos = ko.utils.arrayMap(tiposSelecionados, (item) => item['Item']);

        if (tiposSelecionados.length > 0) {
            return $.grep(mSelf.VeiculosFiltrados(), (veic) => $.inArray(veic[campo](), tipos) > -1);
        }
        else return mSelf.VeiculosFiltrados();
    };

    mSelf.FiltroMultiOperacoes = (campo, lista) =>
        mSelf.FiltroMulti(campo, lista, 'OperacoesVinculadasVeiculo');

    mSelf.FiltroMultiGrupoControle = (campo, lista) =>
        mSelf.FiltroMulti(campo, lista, 'GrupoControle');

    mSelf.FiltroMulti = (campo, lista, nomeCampo) => {
        const tiposSelecionados = ko.utils.arrayFilter(lista, (item) => item.Selecionado() === true);
        const tipos = ko.utils.arrayMap(tiposSelecionados, (item) => item['Item']);

        if (tiposSelecionados.length > 0) {
            const veiculosFiltrados = [];

            ko.utils.arrayForEach(mSelf.VeiculosFiltrados(), (veic) => {
                const retGrep = $.grep(veic[nomeCampo](), (op) => $.inArray(op[campo](), tipos) > -1);
                if (retGrep.length > 0) {
                    veiculosFiltrados.push(veic);
                }
            });

            return veiculosFiltrados;
        }
    }

    mSelf.FiltroDataHora = (maiorque) => {
        if (mSelf.HoraSelecionada() == null || mSelf.HoraSelecionada() == undefined || mSelf.HoraSelecionada() == '')
            mSelf.HoraSelecionada('00:00')

        if (mSelf.DataSelecionada() == null || mSelf.DataSelecionada() == undefined || mSelf.DataSelecionada() == '')
            mSelf.DataSelecionada('');

        const data = mSelf.DataSelecionada().concat('T' + mSelf.HoraSelecionada());
        const dataValida = new Date(data);

        if (isNaN(dataValida.getTime())) {
            vm.ShowMensagemAlerta('A data informada não é válida!');
            return mSelf.VeiculosFiltrados();
        }

        return ko.utils.arrayFilter(mSelf.VeiculosFiltrados(),
            (veic) => maiorque == 'Maior' ? veic.DataHora() >= data : veic.DataHora() <= data);
    };

    mSelf.SetarMarkerVeiculo = (veiculo, visualizarVeiculo) => {
        const condition = (item) => veiculo.CodigoVeiculo() == item.CodigoVeiculo;
        if (visualizarVeiculo) {
            vm.currentMap.toggleMarkers(true, 'veiculos', condition);
        } else {
            vm.currentMap.toggleMarkers(false, 'veiculos', condition);
        }
    };

    mSelf.OnChangeDataHora = () => $('#btnFiltrar').prop('disabled', false);
}