function DemandaPerspectiva(vm, data, codigoDemanda) {
    const mSelf = this;
    mSelf.Data = data;
    mSelf.PermitirAba = ko.observable(false);
    mSelf.UsuarioLogado = ko.observable("");
    mSelf.EmpresaUsuarioLogado = ko.observable("");
    mSelf.QtdDemandas = ko.observable("");
    mSelf.Confirmacao = ko.observable("Deseja realmente excluir esta demanda?");
    mSelf.Titulo = "Demanda";
    mSelf.FiltroDemandas = ko.observable(null);
    mSelf.DemandaParametro = ko.observable(codigoDemanda && codigoDemanda > 0 ? codigoDemanda : 0);

    mSelf.ListaModulosCarregar = ko.observableArray([
        { url: urlGlobal + "DemandaTarefa/Demanda/CarregarGridDemanda", data: { codigoDemanda: mSelf.DemandaParametro() } },
    ]);

    mSelf.ListaFerramentasCarregar = ko.observableArray([
        { url: urlGlobal + "DemandaTarefa/Demanda/CarregarCamadas", data: {} },
    ]);

    mSelf.Init = () => {
        $(".loading-div").show();
        mSelf.CarregarModulos();
        mSelf.SetoresMapa = new ModuloSetoresMapa();
    };

    mSelf.CarregarModulos = () => {
        vm.CarregarFuncionalidades(mSelf.ListaModulosCarregar, (data) => {
            if (data) {
                const kojs = ko.mapping.fromJS(data);

                // Iniciar VIEWMODEL Knockout js pelo JSon;
                const vmInit = new window[kojs.ViewModelKnockout()](kojs, mSelf.Data);
                vm.Modulos.push(vmInit);
                vmInit.Init();
                mSelf.ReconfiguarModulos(vmInit.ModuloId()); //Aplicar enumerador para os módulos.

                vm.Modulos(vm.Modulos().sort((left, right) =>
                    left.Ordem == right.Ordem ? 0 : (left.Ordem < right.Ordem ? -1 : 1)));

                mSelf.CarregarFerramentas();
            } else {
                $(".loading-div").hide();
                vm.ShowMensagemErro("A consulta não retornou resultados!");
            }
        });
    };

    mSelf.DetalheDemanda = new DetalheDemanda();
    mSelf.GaleriaDemanda = new GaleriaFotoDemanda();
    mSelf.DemandaViewModel = ko.observable(new DemandasViewModel());

    mSelf.ReconfiguarModulos = (idModulo) => { };

    mSelf.SignalR = new PersistentConnectionSR({
        mapeamento: urlGlobal + "TunelDemandaTarefa",
        onConnected: () => { console.log('Connectado SignalR'); }
    });

    mSelf.SignalR.SetHandlers(this);

    mSelf.CarregarFerramentas = () => {
        let countFerramentas = 0;
        vm.CarregarFuncionalidades(mSelf.ListaFerramentasCarregar, (data) => {
            if (data) {
                const kojs = ko.mapping.fromJS(data);

                // Iniciar VIEWMODEL Knockout js pelo JSon;
                const vmInit = new window[kojs.ViewModelKnockout()](kojs);
                vm.Ferramentas.push(vmInit);
                if (countFerramentas == mSelf.ListaFerramentasCarregar().length - 1) {
                    HabilitaFuncoes();
                    HabilitaCamadas();
                }

                countFerramentas++;
                vmInit.Init();
                mSelf.ReconfigurarFerramentas(vmInit.FerramentaId());
            }
        });
    };

    mSelf.ReconfigurarFerramentas = (idFerramenta) => { };

    mSelf.DemandasEvento = ko.observableArray([]);

    mSelf.TratarEvento = (tipoEvento, conteudo) => {
        switch (tipoEvento) {
            case 1: mSelf.AtualizaGaleria(conteudo); break;
            case 2: mSelf.AtualizacaoDemanda(conteudo); break;
            case 3: mSelf.AdicionaNotificacao(conteudo); break;
            case 7: mSelf.ExclusaoDemanda(conteudo); break;
            default:
                break;
        }
    };

    mSelf.AtualizaGaleria = (conteudo) => {
        if (mSelf.GaleriaDemanda.CodigoDemanda() != 0 &&
            mSelf.GaleriaDemanda.CodigoDemanda() == conteudo.CodigoDemanda) {
            mSelf.GaleriaDemanda.AtualizarGaleria(conteudo);
        }

        mSelf.AtualizaDemanda(conteudo.CodigoDemanda);
    }

    mSelf.AtualizacaoDemanda = (conteudo) => {
        //Se a modal de edição estiver aberta
        if (mSelf.DemandaViewModel().Demanda().Codigo != null &&
            mSelf.DemandaViewModel().Demanda().Codigo == conteudo && !mSelf.DemandaViewModel().SalvandoDemanda) {

            const demandaViewModel = mSelf.DemandaViewModel();
            demandaViewModel.MsgAlerta("Essa demanda foi editada clique aqui para atualizar as informações.");
            demandaViewModel.EventoAlteracao(true);
            $(".barra-alarme-modal").show();
        }

        mSelf.AtualizaDemanda(conteudo);
        mSelf.AdicionaNotificacao(conteudo);
    }

    mSelf.ExclusaoDemanda = (conteudo) => {
        //Verifica se possui detalhes aberto
        const detalhe = mSelf.DetalheDemanda;
        if (detalhe.DemandaSelecionada != null) {
            if (detalhe.DemandaSelecionada.Codigo() == conteudo) {
                vm.ShowMensagemAlerta("Infelizmente essa demanda foi excluída!");
                $(".sb_demanda").fadeOut("fast");
                vm.Perspectiva.DetalheDemanda.DemandaSelecionada = null;
            }
        }

        //Se a modal de edição estiver aberta
        if (mSelf.DemandaViewModel().Demanda().Codigo != null &&
            mSelf.DemandaViewModel().Demanda().Codigo == conteudo) {
            vm.ShowMensagemAlerta("Infelizmente essa demanda foi excluída!");

            mSelf.DemandaViewModel().Demanda(new Demanda());
            $("#modalAdicionarDemandas").hide();
        }

        mSelf.AdicionaNotificacao(conteudo);
    }

    mSelf.AtualizaDemanda = (codigoDemanda) => {
        //Verifica se possui detalhes aberto
        const detalhe = mSelf.DetalheDemanda;
        if (detalhe.DemandaSelecionada != null) {
            if (detalhe.DemandaSelecionada.Codigo() == codigoDemanda) {
                detalhe.CarregarDemanda(detalhe.DemandaSelecionada, false);
            }
        }
    };

    mSelf.AdicionaNotificacao = (codigoDemanda) => {
        //Adiciona o código da demanda que veio no evento
        if (mSelf.DemandasEvento().indexOf(codigoDemanda) < 0) {
            mSelf.DemandasEvento.push(codigoDemanda);
        }

        //Exibe notificação de evento
        const margin = $(document).height() - $("footer").height() - 69 + "px";
        $(".notificacao-evento").css("margin-top", margin);
        $(".notificacao-evento").show();
    };

    mSelf.ClickNotificacao = (data, evt) => {
        params = { 'codigosDemandas': mSelf.DemandasEvento() };

        //Remove a notificação de atualização
        mSelf.DemandasEvento([]);

        $(".notificacao-evento").hide();
        $(".loading-div").fadeIn();

        //Carrega as demandas que sofreram alteração
        $.ajax({
            url: urlGlobal + "DemandaTarefa/Demanda/CarregarDemandasPorCodigo",
            contentType: 'application/json; charset=utf-8',
            dataType: "json",
            type: "POST",
            data: JSON.stringify(params),
            success: (retorno) => {
                const grid = vm.GetModulo("GridDemandaViewModel");
                const finalizadas = [];
                if (retorno) {
                    ko.utils.arrayForEach(retorno, (item) => {
                        switch (item.Status.trim()) {
                            case "DELETADA": {
                                //Quando a demanda é deletada, remover da grid e do mapa
                                grid.Data().GridInlog.RemoverItemGrid(item);
                                vm.currentMap.removeMarkers('demanda', (marker) => item.Codigo === marker.Codigo);
                                break;
                            }
                            case "FINALIZADA":
                            case "INVALIDA":
                                //Quando a demanda é finalizada ou invalidada alterar item na grid e alterar marker para cinza.
                                const demanda = grid.Data().GridInlog.ProcurarItem(item.Codigo, "Codigo");
                                if (demanda[0] != null) {
                                    finalizadas.push(grid.Data().GridInlog.Data().indexOf(demanda[0]));
                                    grid.Data().GridInlog.AtualizarDadosPorEvento(demanda[0], item);
                                    mSelf.SetoresMapa.PlotarDemandas(demanda);
                                }
                                break;
                            default: {
                                //Quando há outra alteração de status adiciona ou atualiza a grid e o mapa
                                const gridInlog = grid.Data().GridInlog;

                                const demanda = gridInlog.ProcurarItem(item.Codigo, "Codigo");
                                if (demanda[0] != null) {
                                    gridInlog.AtualizarDadosPorEvento(demanda[0], item);
                                } else {
                                    if (grid.Data().Filtro().Filtrado()) {
                                        gridInlog.AdicionarItemGrid(ko.mapping.fromJS(item));
                                        vm.Perspectiva.QtdDemandas("(" + gridInlog.DataFiltrado().length + "/" + gridInlog.Data().length + ")");
                                    } else {
                                        gridInlog.AdicionarItemGridDatas(ko.mapping.fromJS(item));
                                        vm.Perspectiva.QtdDemandas("(" + gridInlog.Data().length + ")");
                                    }
                                }

                                mSelf.SetoresMapa.PlotarDemandas([ko.mapping.fromJS(item)]);
                                break;
                            }
                        }
                    });

                    grid.Data().GridInlog.AtualizarGrid();
                    
                    ko.utils.arrayForEach(finalizadas, (item) =>
                        $(".ordem-html-" + item).parent().parent().css("color", "gray"));
                }

            },
            error: () => vm.ShowMensagemErro("Ocorreu algum erro ao atualizar as demadas"),
            complete: () => $(".loading-div").fadeOut()
        });

    }
}