function ApontamentosRD(modulo) {
    let mSelf = this;
    mSelf.Modulo = modulo;
    mSelf.Funcoes = modulo.ListaFuncoes();

    mSelf.Init = () => { };

    mSelf.AdicionarApontamento = (data) => mSelf.Adicionar(data, true);
    mSelf.AdicionarApontamentoInterno = (linha, evt, parent) => mSelf.Adicionar(parent, false, linha);
    mSelf.AdicionarApontamentoGrupo = (data, evt, parent) => mSelf.AdicionarNivelInterno(parent, data.OpcoesApontamentos, data);

    mSelf.Adicionar = (data, isCabacalho, linha) => {
        let id = `${data.Id}apt${data.IdProximo}`;
        let item = {
            Id: id,
            Codigo: 0,
            Campo: 'SELECIONE',
            ValorValido: ko.observable(false),
            ValoresValidos: ko.observableArray(),
            OpcoesApontamentos: data.OpcoesApontamentos,
            ValorValidoSelecionado: '',
            NomeValorValidoSelecionado: 'SELECIONE',
            Valor: ko.observable(''),
            Data: ko.observable(''),
            Hora: ko.observable(''),
            Distancia: ko.observable(''),
            Duracao: ko.observable(''),
            Mesclado: false,
            Funcao: data,
            Index: data.IdProximo,
            Class: ko.observable(''),
            Pai: null,
            ClassGroup: ko.observable(''),
            NivelInterno: false,
            RDEmEdicao: ko.observable(false),
            RDEmEdicaoValidacao: {
                DataHora: ko.observable(false),
            },
            Posicao: '',
            Status: ''
        };

        if (isCabacalho) {
            data.ListaApontamentos.splice(0, 0, item);
        } else {
            let idx = null;
            const itemPai = data.ListaApontamentos().find(x => x.Pai === linha.Id);

            idx = data.ListaApontamentos().indexOf(itemPai || linha) + 1;
            data.ListaApontamentos.splice(idx, 0, item);
        }
        mSelf.Registrar(data, id);
    };

    mSelf.AdicionarNivelInterno = (funcao, listaApontamentos, linha) => {
        let id = `${funcao.Id}apt${funcao.IdProximo}`;
        let item = {
            Id: id,
            Codigo: 0,
            Campo: 'SELECIONE',
            ValorValido: ko.observable(false),
            ValoresValidos: ko.observableArray(),
            OpcoesApontamentos: listaApontamentos,
            ValorValidoSelecionado: '',
            NomeValorValidoSelecionado: 'SELECIONE',
            Valor: ko.observable(''),
            Data: ko.observable(''),
            Hora: ko.observable(''),
            Distancia: ko.observable(''),
            Duracao: ko.observable(''),
            Mesclado: true,
            Funcao: funcao,
            Index: 0,
            Class: ko.observable(''),
            Pai: linha.Pai || linha.Id,
            ClassGroup: ko.observable(''),
            NivelInterno: true,
            RDEmEdicao: ko.observable(false),
            RDEmEdicaoValidacao: {
                DataHora: ko.observable(false),
            },
            Posicao: '',
            Status: ''
        };
        let l = funcao.ListaApontamentos.indexOf(linha) + 1;
        funcao.ListaApontamentos.splice(l, 0, item);

        linha.Mesclado = true;
        mSelf.Registrar(funcao, id);
    };

    mSelf.ExcluirApontamento = (data) => {
        let filhos = ko.utils.arrayFilter(data.parent.ListaApontamentos(), (item) => item.Pai === data.data.Id);
        ko.utils.arrayForEach(filhos, (item) => data.parent.ListaApontamentos.remove(item));
        data.parent.ListaApontamentos.remove(data.data);

        mSelf.OrdenaIndice(data.parent.ListaApontamentos);
    };

    mSelf.SelecionarApontamento = (data, parent) => {
        mSelf.CarregarApontamentos(mSelf.Modulo.DadosOperacao().MacroSelecionada().Codigo, data.Posicao, null, mSelf.EventSelecionarApontamento, {
            data: data,
            parent: parent
        });
    };

    mSelf.EventSelecionarApontamento = (rs) => {
        rs.parent.Codigo = rs.data.Codigo;
        rs.parent.Campo = rs.data.Descricao;
        rs.parent.Posicao = rs.data.Posicao;
        rs.parent.Status = rs.data.Status;
        rs.parent.ValorValido(false);
        if (rs.ListaApontamentos) {
            rs.parent.ValorValido(true);
            rs.parent.ValoresValidos(rs.ListaApontamentos);
            RegistrarCombobox(`ComboValorApontamento${rs.parent.Id}`);
        }
    };

    mSelf.ExcluirApontamentoInterno = (data, evt, parent) => {
        vm.Perspectiva.AbrirConfirmacao('Deseja excluir esse apontamento?', mSelf.ExcluirApontamento, {
            parent: parent,
            data: data
        });
    };

    mSelf.Registrar = (data, id) => {
        $(`#ComboFuncao${data.Id} .box-sel-funcao`).addClass('disabled');
        $(`#ComboFuncao${data.Id} .box-sel.disabled, #ComboFuncao${data.Id} .box-sel.disabled .sel-val`).off('click');
        RegistrarCombobox(`ComboApontamento${id}`);
        data.IdProximo++;
        mSelf.OrdenaIndice(data.ListaApontamentos);
        AgrupamentoMouse();
    };

    mSelf.OrdenaIndice = (lista) => {
        let j = 0,
            mesclado = false;
        for (let i = 0; i < lista().length; i++) {
            if (lista()[i].Mesclado) {
                lista()[i].Index = j;
                mesclado = true;
                if (i + 1 < lista().length && lista()[i].Pai !== null && lista()[i + 1].Pai === null)
                    j++;
            } else {
                //if (mesclado) j++;
                lista()[i].NovoGrupo = true;
                lista()[i].Index = j++;
                mesclado = false;
            }

            let corLinha = lista()[i].Index % 2 === 0 ? 'white-line' : 'blue-line';
            let classMesclado = lista()[i].Mesclado === true ? ' linked-line' : '';

            if (lista()[i].Mesclado && lista()[i].NovoGrupo)
                lista()[i].ClassGroup(' group-line');

            lista()[i].Class(corLinha + classMesclado + (` grupo${lista()[i].Index}`));
        }
    };

    mSelf.SelecionarValorValido = (data, evt, parent, funcao) => {
        let filhos = ko.utils.arrayFilter(funcao.ListaApontamentos(), (item) => item.Pai === parent.Id);
        ko.utils.arrayForEach(filhos, (item) => funcao.ListaApontamentos.remove(item));
        mSelf.CarregarApontamentos(mSelf.Modulo.DadosOperacao().MacroSelecionada().Codigo, data.Posicao, null, mSelf.EventSelecionarValorValido, {
            data: data,
            parent: parent,
            funcao: funcao
        });
    };

    mSelf.EventSelecionarValorValido = (rs) => {
        rs.parent.ValorValidoSelecionado = rs.data;
        if (rs.ListaApontamentos)
            mSelf.AdicionarNivelInterno(rs.funcao, rs.ListaApontamentos, rs.parent);
    };

    mSelf.CarregarApontamentos = (idMacro, posicao, funcao, callback, callparams) => {
        params = {
            codigoMacro: idMacro,
            posicao: posicao
        };
        $.ajax({
            url: `${urlGlobal}EditorRD/EditorRD/CarregarAtividadesPorPosicao`,
            dataType: 'json',
            type: 'GET',
            data: ko.toJS(params),
            beforeSend: () => $('.loading-div').fadeIn(),
            success: (data) => {
                if (data && funcao) {
                    funcao.OpcoesApontamentos = data;
                    mSelf.AdicionarApontamento(funcao);
                }
                if (callback) {
                    callparams.ListaApontamentos = data;
                    callback(callparams);
                }
                $('.loading-div').fadeOut();
            },
            error: () => $('.loading-div').fadeOut()
        });
    };
}
