<?php include_once('../../config.php') ?>
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>Sisplan Web | Loja</title>
  <!-- Tell the browser to be responsive to screen width -->
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- Font Awesome -->
  <link rel="stylesheet" href="../plugins/fontawesome-free/css/all.min.css?versao=3.264.8.1">
  <!-- Theme style -->
  <link rel="stylesheet" href="../dist/css/adminlte.min.css?versao=3.264.8.1">
  <!-- overlayScrollbars -->
  <link rel="stylesheet" href="../plugins/overlayScrollbars/css/OverlayScrollbars.min.css?versao=3.264.8.1">
  <!-- Daterange picker -->
  <link rel="stylesheet" href="../plugins/daterangepicker/daterangepicker.css?versao=3.264.8.1">
  <!-- Google Font: Source Sans Pro -->
  <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet">
  <link rel="stylesheet" href="../dist/css/animate.min.css?versao=3.264.8.1">
  <link rel="stylesheet" href="../dist/css/custom.css?versao=3.264.8.1">
  <link rel="stylesheet" href="../dist/css/sisplan.css?versao=3.264.8.1">
  <link rel="stylesheet" href="../dist/css/cadastro.css?versao=3.264.8.1">
  <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/styles/default.min.css?versao=3.264.8.1">
  <link rel="stylesheet" type="text/css" href="../dist/css/dataTables.bootstrap4.min.css?versao=3.264.8.1" />
  <link rel="shortcut icon" href="../favicon.ico">

  <link href='../dist/css/bootstrap.min.css?versao=3.264.8.1'>
  <link rel="stylesheet" href="../dist/css/normalize.css?versao=3.264.8.1">
  <link rel="stylesheet" href="../plugins/select2/css/select2.min.css?versao=3.264.8.1">
  <link rel="stylesheet" href="../plugins/select2-bootstrap4-theme/select2-bootstrap4.min.css?versao=3.264.8.1">
  <link rel="stylesheet" href="../plugins/toastr/toastr.min.css?versao=3.264.8.1">
  <style>
    .progress-bar {
      background-color: var(--primary-color) !important;
    }

    .chart {
      width: 100%;
    }

    .custom-tooltip {
      background: #fff;
      border: 1px solid #dcdcdc;
      border-radius: 8px;
      box-shadow: 0 4px 14px rgba(0, 0, 0, 0.12);
      padding: 10px 12px;
      font-size: 14px;
      min-width: 150px;
    }

    .custom-tooltip .tt-title {
      font-weight: bold;
      margin-bottom: 8px;
      color: #333;
    }

    .custom-tooltip .tt-row {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 10px;
      margin: 6px 0;
    }

    .custom-tooltip .tt-left {
      display: flex;
      align-items: center;
      gap: 8px;
      color: #333;
    }

    .custom-tooltip .dot {
      width: 10px;
      height: 10px;
      border-radius: 50%;
      display: inline-block;
    }

    .custom-tooltip .meta-dot {
      width: 10px;
      height: 2px;
      border-top: 2px dashed #666;
      display: inline-block;
    }

    .custom-tooltip .value {
      font-weight: bold;
      color: #111;
    }

    .card-body {
      padding: 0 !important;
    }
  </style>
  <!--Load the AJAX API-->
  <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
</head>

<body class="hold-transition sidebar-mini layout-fixed">
  <div class="container-fluid">

    <!-- Content Wrapper. Contains page content -->
    <!-- Content Header (Page header) -->
    <section class="content-header">
      <div class="container-fluid">
        <div class="row mb-2">
          <div class="col-sm-6 flex">
            <div style="text-align:center;" class="mt-2">
              <button class="btn d-none" onclick="toggleTheme()">
                <i style="font-size: 25px" id="themeIcon" class="text-white fas"></i>
              </button>
            </div>
            <h1 class="m-0 text-dark" id="txtNome">
            </h1>
            <button class="btn btn-sm btn-sisp btn-danger m-2 d-none" id="btnFiltros">Filtros</button>
          </div>
          <div class="col-sm-6">
            <ol class="breadcrumb float-sm-right">

              <li class="breadcrumb-item active">Teste-Dashboard</li>
            </ol>
          </div>
        </div>
      </div><!-- /.container-fluid -->
    </section>
    <!-- /.content-header -->

    <!-- Main content -->
    <section class="content-header">
      <div class="container-fluid">
        <div class="row d-none" id="card-carregando">
          <div class="col-sm-12" style="text-align:center">
            <h5>Carregando dashboard</h5>
            <div class="progress progress-stripedactive">
              <div class="progress-bar progress-bar-striped bg-danger progress-bar-animated" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%">
              </div>
            </div>
          </div>
        </div>
        <div id="conteudo" class="row">
          <div class="col-sm-12">
            <textarea id="txtSelect" class="d-none" rows="10" placeholder="Monte o SQL aqui"></textarea>
            <div id="resultados" class="col-sm-12 table-responsive d-none">
            </div>
          </div>
          <div id="chart_div"></div>
        </div>
        <div id="modal-conteudos"></div>
        <div class="modal fade" id="modal-info" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
          <div class="modal-dialog modal-xl">
            <div class="modal-content">
              <div class="modal-header">
                <h4 id="modal-info-title" class="modal-title">Vendas Semanais</h4>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                  <span aria-hidden="true">&times;</span>
                </button>
              </div>
              <div class="modal-body">
                <div class="row">
                  <div class="col-sm-12">
                    <div class="table-responsive" id="modal-info-table">
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <div class="modal" id="mapaModal" tabindex="-1" role="dialog" aria-labelledby="mapaModalLabel">
        <div id="pnlMapaEstado" class="modal-dialog modal-lg" role="document">
          <div class="modal-content">
            <div class="modal-header">
              <h4 class="modal-title" id="mapaModalLabel">Estado</h4>
              <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
            </div>
            <div class="modal-body" style="height: 98%;max-width:98%">
              <div id="mapa_estado" style="height: 80vh;display: flex;justify-content: center;"></div>
              <ul id="cidades_vendas" style="clear: none; margin-right: 70px; float: right;">
                <li id="cidVerde">
                  <font color="#6baa01">Cidades em verde com vendas:</font> <span id="cidades_com_vendas"></span>
                </li>
                <li id="cidVermelho">
                  <font color="red">Cidades em vermelho com clientes e sem vendas:</font> <span id="cidades_com_clientes"></span>
                </li>
                <li id="cidAzul">
                  <font color="blue"> Cidades em azul sem clientes: </font><span id="cidades_sem_clientes"></span>
                </li>
                <li id="cidAmarelo">
                  <font color="#ffd700">Cidades em amarelo sem clientes e sem vendas:</font> <span id="cidades_sem_clientes_sem_vendas"></span>
                </li>
              </ul>
              <p style="font-size: 9px;" id="mapa_modal_msg">Estados em azul não houve vendas.</p>
            </div>
          </div>
        </div>
      </div>
      <?php
      include_once('../../modais.php');
      ?>
      <!-- jQuery -->
      <script src="../plugins/jquery/jquery.min.js?versao=3.264.8.1"></script>
      <!-- jQuery UI 1.11.4 -->
      <script src="../plugins/jquery-ui/jquery-ui.min.js?versao=3.264.8.1"></script>
      <!-- Resolve conflict in jQuery UI tooltip with Bootstrap tooltip -->
      <script>
        $.widget.bridge('uibutton', $.ui.button)
      </script>

      <!-- Bootstrap 4 -->
      <script src="../plugins/bootstrap/js/bootstrap.bundle.min.js?versao=3.264.8.1"></script>
      <!-- Sparkline -->
      <script src="../plugins/sparklines/sparkline.js?versao=3.264.8.1"></script>
      <script src="../dist/js/sisplan.js?versao=3.264.8.1"></script>
      <script type="text/javascript" src="../utils/funcoes.js?versao=3.264.8.1"></script>
      <script src="../dist/js/adminlte.min.js?versao=3.264.8.1"></script>
      <script src="../dist/js/jquery.dataTables.min.js?versao=3.264.8.1"></script>
      <script type="text/javascript" src="../dist/js/loadingoverlay.min.js?versao=3.264.8.1"></script>
      <script type="text/javascript" src="../dist/js/dataTables.bootstrap4.min.js?versao=3.264.8.1"></script>
      <script type="text/javascript" src="../dist/js/sum().js?versao=3.264.8.1"></script>
      <script src="../dist/js/dataTables.keyTable.js?versao=3.264.8.1"></script>
      <script src="../utils/cookies.js?versao=3.264.8.1"></script>
      <script src="../dist/js/requisicoes.js?versao=3.264.8.1"></script>
      <script type="text/javascript" src="../plugins/jszip/jszip.min.js?versao=3.264.8.1"></script>
      <script type="text/javascript" src="../plugins/pdfmake/pdfmake.min.js?versao=3.264.8.1"></script>
      <script type="text/javascript" src="../plugins/pdfmake/vfs_fonts.js?versao=3.264.8.1"></script>
      <script type="text/javascript" src="../plugins/datatables-buttons/js/dataTables.buttons.min.js?versao=3.264.8.1"></script>
      <script type="text/javascript" src="../plugins/datatables-buttons/js/buttons.html5.min.js?versao=3.264.8.1"></script>
      <script src="../dist/js/sql-formatter.min.js?versao=3.264.8.1"></script>
      <script src="../plugins/select2/js/select2.full.min.js?versao=3.264.8.1"></script>
      <script src="../dist/js/underscore.js?versao=3.264.8.1"></script>
      <script src="../plugins/toastr/toastr.min.js?versao=3.264.8.1"></script>
      <script type="text/javascript" src="../config.js?versao=3.264.8.1"></script>
      <script type="text/javascript" src="../dist/js/apexcharts.js?versao=3.264.8.1"></script>
      <script type="text/javascript" src="../plugins/syncfusion/js/fusioncharts.js"></script>
      <script type="text/javascript" src="../plugins/syncfusion/js/fusioncharts.charts.js"></script>
      <script type="text/javascript" src="../plugins/syncfusion/js/fusioncharts.widgets.js"></script>
      <script type="text/javascript" src="../plugins/syncfusion/js/fusioncharts.maps.js"></script>
      <script type="text/javascript" src="../plugins/syncfusion/js/fusioncharts.brazil.js"></script>
      <script type="text/javascript" src="../plugins/syncfusion/js/fusioncharts.theme.fint.js"></script>
      <script type="text/javascript" src="../plugins/syncfusion/js/sisplan_functions.js"></script>
      <script type="text/javascript" src="../plugins/syncfusion/js/fusioncharts.theme.candy.js"></script>
      <script type="text/javascript">
        google.charts.load('current', {
          'packages': ['corechart'],
          language: 'pt-BR'
        });
      </script>

      <script>
        $('#rodape').addClass('d-none');
        $(document).ready(async function() {

          ipInterno = '<?php echo IP_INTERNO; ?>';
          ipExterno = '<?php echo IP_EXTERNO; ?>';
          basicAuth = '<?php echo BASIC_AUTH; ?>';
          const temAcesso = await temAcessoTela('CADASTRO_DASHBOARD');
          if (!temAcesso.resultado) {
            toastrAcesso(temAcesso, '<?php echo BASE_URI; ?>');
            return;
          }

          var queryString = window.location.href;
          var parametros = queryString.split('/');
          var id_dashboard = parametros[parametros.length - 1];
          var arrDados = [];
          var arrGraficos = [];
          var contadorGrafico = 0;
          const filtros = [];

          function preencherDataInput(inputSelector, parametro) {
            const $input = $(inputSelector);
            const dataAtual = new Date();

            switch (parametro) {
              case 0:
              case '':
                // Não fazer nada
                break;
              case 1:
                // Data atual
                $input.val(dataAtual.toISOString().slice(0, 10));
                break;
              case 2:
                // Primeiro dia do mês corrente
                $input.val(new Date(dataAtual.getFullYear(), dataAtual.getMonth(), 1).toISOString().slice(0, 10));
                break;
              case 3:
                // Último dia do mês corrente
                $input.val(new Date(dataAtual.getFullYear(), dataAtual.getMonth() + 1, 0).toISOString().slice(0, 10));
                break;
              case 4:
                // Primeiro dia do ano corrente
                $input.val(new Date(dataAtual.getFullYear(), 0, 1).toISOString().slice(0, 10));
                break;
              case 5:
                // Último dia do ano corrente
                $input.val(new Date(dataAtual.getFullYear(), 11, 31).toISOString().slice(0, 10));
                break;
              default:
                console.warn("Parâmetro inválido.");
            }
          }

          async function retornaEmpresasUsuario() {
            const dadosSelect = {
              orderBy: ['EMPRESA.EMP_PAT'],
              tabela: `ACESSO_EMPRESA`,
              leftJoin: [{
                "tabela": "EMPRESA",
                "condicao": "REPLACE(EMPRESA.EMP_PAT,'_','') = ACESSO_EMPRESA.EMPRESA"
              }],
              camposSelect: ['EMPRESA.EMP_ID', 'ACESSO_EMPRESA.EMPRESA', 'EMPRESA.EMP_NOME', 'EMPRESA.EMP_FANTASIA'],
              where: [`ACESSO_EMPRESA.USUARIO = '${getCookie('cod_usuario')}'`],
            };
            const retornoSelect = await retornaJsonPesquisaPadrao(JSON.stringify(dadosSelect));
            if (!retornoSelect) {
              return '';
            }
            return retornoSelect;
          }

          async function buscaFiltros() {
            const url = `/sisplan/funcoes/v1/pesquisa?`;
            const pesquisa = {
              "tabela": "dash_filtros",
              "camposSelect": ["id", "nome", "tipo", "tabela", "campo", "valor_padrao", "obrigatorio", "varios", "label", "campo_desc", "utiliza_emp_id", "opcao_data"],
              "where": [`id_dash = ${id_dashboard}`],
              "orderBy": ['id']
            }
            try {
              try {
                const response = await requisicao('GET', url,
                  `JSON=${JSON.stringify(pesquisa)}`,
                  null);

                if (!response) {
                  return;
                }
                const jsonStr = await response.json();
                if (response.status != 200) {
                  msgErro(jsonStr['RESULT'][0].mensagem)
                  return;
                }

                const dados = jsonStr['RESULT'][0];
                const filtrosList = [];
                const listaPesquisasDinamicas = [];
                while (filtros.length) {
                  filtros.pop();
                }

                for (let i = 0; i < dados.length; i++) {
                  const element = dados[i];
                  const ehTexto = element.TIPO == 0;
                  const ehData = element.TIPO == 1;
                  const ehNumero = element.TIPO == 2;
                  const defaultValue = element.VALOR_PADRAO != '' ? element.VALOR_PADRAO : '';
                  const obrigatorio = element.OBRIGATORIO == 'S' ? 'required' : '';
                  const utilizaEmpId = element.UTILIZA_EMP_ID == 'S';

                  filtros.push({
                    component: `txt-filtro-${element.NOME}`,
                    label: element.LABEL,
                    name: element.NOME,
                    required: element.OBRIGATORIO == 'S',
                    emp: element.UTILIZA_EMP_ID == 'S',
                    data: ehData
                  })

                  // monta o input

                  if (ehData) {
                    const dataElement = `<div class="col-lg-12 col-md-12 col-sm-12">` +
                      `<label data-error="wrong" data-success="right" for="txt-filtro-${element.NOME}">${element.LABEL}</label>` +
                      `  <div class="input-group">` +
                      `    <input type="date" max="2500-12-31" ${obrigatorio} autocomplete="off" value="${defaultValue}" class="input-default focus form-control" id="txt-filtro-${element.NOME}">` +
                      `  </div>` +
                      ` </div>`;
                    filtrosList.push(dataElement);
                  } else if (ehTexto) {

                    if (element.VARIOS == 'S') {
                      const textElement = `<div class="col-lg-12 col-md-12 col-sm-12">` +
                        `<label data-error="wrong" data-success="right" for="txt-filtro-${element.NOME}">${element.LABEL} </label>` +
                        `<div class="relative">` +
                        `   <div class="input-group">` +
                        `     <select ${obrigatorio} class="js-example-programmatic js-states form-control" id="txt-filtro-${element.NOME}" name="txt-filtro-${element.NOME}" multiple="multiple"></select>` +
                        `     <div class="input-group-append">` +
                        `       <button class="btn bg-danger" id="btn-filtro-${element.NOME}" name="btn-filtro-${element.NOME}" data-button="absolute" type="button"><i class="m-0 p-0 fas fa-search"></i></button>` +
                        `       <button class="btn bg-danger" id="btn-limpa-filtro-${element.NOME}" type="button"><i class="m-0 p-0 fas fa-trash"></i></button>` +
                        `     </div>` +
                        `    </div>` +
                        ` </div>` +
                        `</div>`;

                      listaPesquisasDinamicas.push(async () => {
                        const pesquisa = {
                          camposSelect: [`${element.CAMPO}`, `${element.CAMPO_DESC}`],
                          tabela: `${element.TABELA}`,
                          where: []
                        }

                        if (pesquisa.tabela.toUpperCase() == 'EMPRESA') {
                          const empresasUsuario = await retornaEmpresasUsuario();
                          const empresasFiltro = empresasUsuario != '' ? await formataListas(empresasUsuario.map(emp => emp.EMPRESA).toString()) : '';
                          if (empresasFiltro != '') {
                            pesquisa.where.push(` EMP_ID IN (SELECT EMP_ID FROM EMPRESA WHERE REPLACE(EMP_PAT, '_','') IN (${empresasFiltro}))`)
                          }
                        }

                        if (utilizaEmpId) {
                          pesquisa.where.push(` EMP_ID = ${getCookie('emp_id')}`);
                        }

                        $('#txt-filtro-' + element.NOME).pesquisa_variosServerside(1, `${JSON.stringify(pesquisa)}`, element.CAMPO, element.CAMPO_DESC);
                        $('#btn-filtro-' + element.NOME).pesquisa_serversideSel('#txt-filtro-' + element.NOME, `${JSON.stringify(pesquisa)}`, `Pesquisa ${pesquisa.tabela}`);
                        $('#btn-limpa-filtro-' + element.NOME).on('click', function() {
                          $('#txt-filtro-' + element.NOME).empty().trigger('change')
                          $('#txt-filtro-' + element.NOME).val('');
                          $('#txt-filtro-' + element.NOME).attr('data-chave', '');
                          $('#txt-filtro-' + element.NOME).attr('data-desc', '');
                        });

                        if (defaultValue != '') {
                          $('#txt-filtro-' + element.NOME).append(new Option(defaultValue, pegaChave(defaultValue), true, true));
                          $('#txt-filtro-' + element.NOME).trigger('change');
                        }
                      });

                      filtrosList.push(textElement);


                    } else {
                      const textElement = `<div class="col-lg-12 col-md-12 col-sm-12"> ` +
                        `  <label data-error="wrong" data-success="right" for="txt-filtro-${element.NOME}">${element.LABEL}</label>` +
                        `  <div class="form-group input-group">` +
                        `    <input ${obrigatorio} type="text" class="input-default focus form-control ui-autocomplete-input" id="txt-filtro-${element.NOME}" name="txt-filtro-${element.NOME}" autocomplete="off">` +
                        `    <div class="input-group-append">` +
                        `      <button class="btn bg-danger" id="btn-filtro-${element.NOME}" name="btn-filtro-${element.NOME}" data-button="absolute" type="button"><i class="m-0 p-0 fas fa-search"></i></button>` +
                        `      <button class="btn bg-danger" id="btn-limpa-filtro-${element.NOME}" type="button"><i class="m-0 p-0 fas fa-trash"></i></button>` +
                        `    </div>` +
                        `  </div>` +
                        `</div>`;
                      listaPesquisasDinamicas.push(async () => {
                        const pesquisa = {
                          camposSelect: [`${element.CAMPO} CHAVE`, `${element.CAMPO_DESC} DESCRICAO`],
                          tabela: `${element.TABELA}`,
                          where: []
                        }

                        if (pesquisa.tabela.toUpperCase() == 'EMPRESA') {
                          const empresasUsuario = await retornaEmpresasUsuario();
                          const empresasFiltro = empresasUsuario != '' ? await formataListas(empresasUsuario.toString()) : '';
                          if (empresasFiltro != '') {
                            pesquisa.where.push(` EMP_ID IN (SELECT EMP_ID FROM EMPRESA WHERE REPLACE(EMP_PAT, '_','') IN (${empresas}))`)
                          }
                        }

                        if (utilizaEmpId) {
                          pesquisa.where.push(` EMP_ID = ${getCookie('emp_id')}`);
                        }

                        $('#txt-filtro-' + element.NOME).autocompleta(2, `JSON=${JSON.stringify(pesquisa)}`);
                        $('#btn-filtro-' + element.NOME).pesquisa('#txt-filtro-' + element.NOME, 'CHAVE', 'DESCRICAO', `/sisplan/funcoes/v1/pesquisa?JSON=${JSON.stringify(pesquisa)}`, `Pesquisa de ${pesquisa.tabela}`, pesquisa.tabela.toUpperCase());
                        $('#btn-limpa-filtro-' + element.NOME).on('click', function() {
                          limpaValor('#txt-filtro-' + element.NOME);
                        });
                      });

                      filtrosList.push(textElement);
                    }
                  } else if (ehNumero) {
                    const numberElement = `<div class="col-lg-12 col-md-12 col-sm-12">` +
                      `  <label data-error="wrong" data-success="right" for="txt-filtro-${element.NOME}">${element.LABEL}</label>` +
                      `  <div class="input-group">` +
                      `    <input ${obrigatorio} type="number" autocomplete="off" value="${defaultValue}" class="input-default focus form-control" id="txt-filtro-${element.NOME}">` +
                      `  </div>` +
                      `</div>`;
                    filtrosList.push(numberElement);
                  }
                }

                $('#modal-conteudos').html(`<div class="modal fade" id="modal-filtros-${id_dashboard}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> ` +
                  `<div class="modal-dialog modal-lg">` +
                  `  <div class="modal-content">` +
                  `    <div class="modal-header">` +
                  `      <h4 class="modal-title">Filtros</h4>` +
                  `      <button type="button" class="close" data-dismiss="modal" aria-label="Close">` +
                  `        <span aria-hidden="true">&times;</span>` +
                  `      </button>` +
                  `    </div>` +
                  `    <div class="modal-body">` +
                  `      <div id="modal-filtros-${id_dashboard}-conteudo" class="row">` +
                  `      </div>` +
                  `    </div>` +
                  `<div class="modal-footer">` +
                  `<button id="btnConsultar" class='btn btn-primary btn-sisp' type='button'><span class="fas fa-search"></span> Consultar </button>` +
                  `</div>` +
                  `</div>` +
                  `   </div>` +
                  `  </div>` +
                  ` </div>`);

                for (let i = 0; i < filtrosList.length; i++) {
                  $(`#modal-filtros-${id_dashboard}-conteudo`).append(filtrosList[i]);
                  if (dados[i].TIPO == 1) {
                    preencherDataInput(`#txt-filtro-${dados[i].NOME}`, dados[i].OPCAO_DATA ?? 0);
                  }

                }

                for (let i = 0; i < listaPesquisasDinamicas.length; i++) {
                  listaPesquisasDinamicas[i]();
                }


                if (filtrosList.length > 0) {
                  $('#btnFiltros').removeClass('d-none');
                } else {
                  $('#btnFiltros').addClass('d-none');
                }

                $('#btnFiltros').off();
                $('#btnFiltros').on('click', function() {
                  $(`#modal-filtros-${id_dashboard}`).modal('show');
                });

                $('#btnConsultar').off('click');
                $('#btnConsultar').on('click', async function() {
                  try {
                    $('#conteudo').html(`<div class="col-sm-12">
                  <textarea id="txtSelect" class="d-none" rows="10"></textarea>
                  <div id="resultados" class="col-sm-12 table-responsive d-none">
                  </div>
                </div>`);
                    await criaAviso('Carregando Dados');
                    $('#btnConsultar').prop('disabled', true);
                    if (await buscaDatasets(id_dashboard)) {
                      await buscaGraficos(id_dashboard);
                    }
                  } finally {
                    $(`#modal-filtros-${id_dashboard}`).modal('hide');
                    $('#btnConsultar').prop('disabled', false);
                    await destroiAviso();
                  }
                });
              } catch (error) {
                console.error(error);
                $('#btnConsultar').prop('disabled', false);
                msgErro('Não foi possível buscar os dados dos dashboards.');
              }
            } finally {
              $('#btnConsultar').prop('disabled', false);
            }
          }

          async function buscaDashboard() {
            const _url = `/sisplan/funcoes/v1/pesquisa?`;
            try {
              try {
                var response = await requisicao('GET', _url,
                  `JSON={ "tabela":"dash_web", "camposSelect":["nome"], "where": ["id = '${id_dashboard}'"] }`,
                  null);

                if (!response) {
                  return;
                }
                var jsonStr = await response.json();
                if (response.status != 200) {
                  msgErro(jsonStr['RESULT'][0].mensagem)
                  return;
                }
                $('#txtNome').html(jsonStr.RESULT[0][0].NOME);
              } catch (error) {
                console.error(error);
                msgErro('Não foi possível buscar os dados dos dashboards.');
              }
            } finally {

            }
          }

          function formataDataFiltro(data) {
            const [ano, mes, dia] = data.split('-');
            return `${dia}.${mes}.${ano}`;
          }

          async function buscaDatasets() {
            const _url = `/sisplan/funcoes/v1/pesquisa?`;
            try {
              try {
                var response = await requisicao('GET', _url,
                  `JSON={ "tabela":"dataset_web", "camposSelect":["id","nome","sql", "cor"], "where": ["id_dash = '${id_dashboard}'"] }&REPLACE_LINE_BREAK=true`,
                  null);
                if (!response) {
                  return;
                }
                var jsonStr = await response.json();
                if (response.status != 200) {
                  msgErro(jsonStr['RESULT'][0].mensagem)
                  return;
                }

                for (let i = 0; i < filtros.length; i++) {
                  const filtro = filtros[i];
                  if ((filtro.required) && ($('#' + filtro.component).val() == '')) {
                    msgAlerta('Campo ' + filtro.label.replaceAll(':', '') + ' é obrigatório, verifique.');
                    return;
                  }
                }

                arrDados.splice(0, arrDados.length);
                for (let i = 0; i < jsonStr['RESULT'][0].length; i++) {
                  const dataset = jsonStr['RESULT'][0][i];
                  $('#txtSelect').val(dataset.SQL);
                  const dados = {}
                  const sqlReplaced = $('#txtSelect').val()
                    .replaceAll('&#013;', '\r\n')
                    .replaceAll('  ', ' ')
                    .replaceAll(':EMP_ID', getCookie('emp_id'))
                    .replaceAll(':EMP_PAT', getCookie('empresa'))
                    .replaceAll(':COD_USUARIO', getCookie('cod_usuario'));

                  let sqlReplaceByFilter = sqlReplaced;

                  for (let x = 0; x < filtros.length; x++) {
                    const filtro = filtros[x];

                    if (filtro.data) {
                      if ($('#' + filtro.component).val() != '') {
                        sqlReplaceByFilter = sqlReplaceByFilter.replaceAll(':' + filtro.name, formataDataFiltro($('#' + filtro.component).val()))
                      } else {
                        sqlReplaceByFilter = sqlReplaceByFilter.replaceAll(':' + filtro.name, "''");
                      }
                    } else if ($('#' + filtro.component).val() != '') {
                      if ($('#' + filtro.component).is('select')) {
                        sqlReplaceByFilter = sqlReplaceByFilter.replaceAll(':' + filtro.name, await formataListas($('#' + filtro.component).val().toString()));
                      } else {
                        sqlReplaceByFilter = sqlReplaceByFilter.replaceAll(':' + filtro.name, $('#' + filtro.component).val());
                      }
                    } else {
                      sqlReplaceByFilter = sqlReplaceByFilter.replaceAll(':' + filtro.name, "''");
                    }
                  }

                  dados.data = await rotinaValidarSQL(sqlReplaceByFilter),
                    dados.id = dataset.ID,
                    dados.nome = dataset.NOME,
                    dados.cor = dataset.COR
                  arrDados.push(dados);
                }
                return true;

              } catch (error) {
                console.error(error);
                msgErro('Não foi possível buscar os dados dos datasets.');
              }
            } finally {

            }
          }

          async function buscaGraficos() {
            const _url = `/Sisplan/dashboard/v1/grafico?`;
            try {
              try {
                var response = await requisicao('GET', _url, `ID_DASH=${id_dashboard}`, null, 60000);
                if (!response) {
                  return;
                }
                var jsonStr = await response.json();
                if (response.status != 200) {
                  msgErro(jsonStr['RESULT'][0].mensagem)
                  return;
                }

                for (let i = 0; i < jsonStr.length; i++) {
                  const grafico = jsonStr[i];
                  grafico.DATASET = grafico.DATASET.replace('\r\n', '');
                  const arrDataSets = grafico.DATASET.split(', ');
                  grafico.DATASET_INFO = [];
                  arrDataSets.forEach(element => {
                    const nome_dataset = arrDados.find(dado => dado.id == element).nome;
                    grafico.DATASET_INFO.push(nome_dataset);
                  });

                  switch (grafico.TIPO) {
                    case 0:
                      await criaCard(grafico);
                      break;
                    case 1:
                      await criaGrafico(grafico);
                      break;
                    case 2:
                      await criaGrafico(grafico);
                      break;
                    case 3:
                      await criaGrafico(grafico);
                      break;
                    case 4:
                      await criaGrafico(grafico);
                      break;
                    case 5:
                      await criaGrafico(grafico);
                      break;
                    case 6:
                      await criaGrafico(grafico);
                      break;
                    case 7:
                      await criaGrafico(grafico);
                      break;
                    default:
                      break;
                  }
                  arrGraficos.push(grafico);
                }

              } catch (error) {
                console.error(error);
                msgErro('Não foi possível buscar os dados dos gráficos.');
              }
            } finally {

            }
          }

          async function incrementaContador() {
            contadorGrafico++;
          }

          async function converteProporcaoEmTamanhoBootstrap(proporcao) {
            return parseInt(proporcao) * 2;
          }

          async function ajustaDadosDataSetMultiSerie(dados, totalDataSets) {
            function ordenaArray(array) {
              array.sort((a, b) => {
                if (a[2] > b[2]) {
                  return 1;
                }
                if (a[2] < b[2]) {
                  return -1;
                }
                return 0;
              })
            }

            const concatenacao = _.union(...dados);
            const arrConcatenado = concatenacao;
            ordenaArray(arrConcatenado);
            let arrNovoArray = [];
            for (let i = 0; i < arrConcatenado.length; i++) {
              const arrSeparado = arrConcatenado[i];
              const arrControleEixo = [];
              for (let y = 0; y < totalDataSets; y++) {
                const arrDadosAtual = dados[y];
                if (arrControleEixo.length == 0) {
                  arrControleEixo.push(arrSeparado[0]);
                }
                const iPosicaoAtual = arrDadosAtual.findIndex(obj => {
                  return obj[0] == arrSeparado[0];
                });
                if (iPosicaoAtual == -1) {
                  arrControleEixo.push(0);
                } else {
                  arrControleEixo.push(arrDadosAtual[iPosicaoAtual][1]);
                }
              }
              const iPosicaoNovoArray = arrNovoArray.findIndex(obj => {
                return obj[0] == arrSeparado[0];
              });

              if (iPosicaoNovoArray == -1) {
                arrNovoArray.push(arrControleEixo);
              }
            }
            arrNovoArray = _.groupBy(arrNovoArray, 0);
            arrNovoArray = _.map(arrNovoArray);
            return arrNovoArray;
          };

          async function utilizaGoogleCharts(dados, grafico) {
            const ordemDecrescente = grafico.TIPO_ORDENACAO == 0;
            const semOrdenacao = grafico.TIPO_ORDENACAO == -1;
            const tipoApresentacaoInteiro = grafico.TIPO_APRESENTACAO == 0;
            const tipoApresentacaoDecimal = grafico.TIPO_APRESENTACAO == 1;
            const tipoApresentacaoMonetario = grafico.TIPO_APRESENTACAO == 2;
            const formatoValor = tipoApresentacaoMonetario ? 'currency' : 'decimal';
            const tipoEhColuna = grafico.TIPO == 2;
            const tipoEhBarra = grafico.TIPO == 1;
            const tipoEhLinha = grafico.TIPO == 3;
            const tipoEhPizza = grafico.TIPO == 4;
            const tipoEhRosca = grafico.TIPO == 5;
            const tamCard = grafico.TAM_CARD != '' ? grafico.TAM_CARD.trim() : '250';


            google.charts.setOnLoadCallback(drawChart);

            async function drawChart() {

              let arrDadosDataSets = [];
              let data = new google.visualization.DataTable();
              for (let i = 0; i < dados.length; i++) {
                let regAgrupados = [];
                const dataset = dados[i]; // numero de datasets
                for (let y = 0; y < dataset.length; y++) {
                  let totGrupo = 0;
                  const registros = dataset[y]; // array de registros por dataset
                  for (let z = 0; z < registros.length; z++) {
                    totGrupo += registros[z][grafico.VALOR];
                    if (z == registros.length - 1) {
                      regAgrupados.push([String(registros[z][grafico.EIXO]), totGrupo, registros[z][grafico.CAMPO_ORDENACAO]]);
                    }
                  }
                }
                arrDadosDataSets.push(regAgrupados);
              }

              if (arrDadosDataSets.length > 1) {
                //verificar amanha para ao criar mais de um array de dados, verificar a coluna se existe em todos datasets, se nao criar com valor 0...
                const arrTeste = await ajustaDadosDataSetMultiSerie(arrDadosDataSets, grafico.DATASET_INFO.length);
                let novoArray = [];
                const arrDadosFinais = [];

                data.addColumn('string', grafico.EIXO);
                for (let i = 0; i < arrDadosDataSets.length; i++) {
                  data.addColumn('number', grafico.DATASET_INFO[i]);
                }
                novoArray = arrTeste;

                for (let i = 0; i < novoArray.length; i++) {
                  const dataNovoArray = novoArray[i];
                  const arrDadosAtuais = [];
                  for (let y = 0; y < dataNovoArray.length; y++) {
                    const registro = dataNovoArray[y];
                    for (let z = 0; z < registro.length; z++) {
                      if (!((y != 0) && (z == 0))) { //nao repetir a legenda do dataset...
                        const dadoReg = registro[z];
                        arrDadosAtuais.push(dadoReg);
                      }
                    }
                  }
                  while (arrDadosAtuais.length - 1 < grafico.DATASET_INFO.length) {
                    arrDadosAtuais.push(0);
                  }
                  arrDadosFinais.push(arrDadosAtuais);
                }
                data.addRows(arrDadosFinais);
              } else {
                data.addColumn('string', grafico.EIXO);
                data.addColumn('number', grafico.VALOR);
                if (tipoEhColuna || tipoEhBarra || tipoEhLinha) {
                  if (!semOrdenacao && ordemDecrescente) {
                    arrDadosDataSets[0] = _.sortBy(arrDadosDataSets[0], 1).reverse();
                  } else if (!semOrdenacao) {
                    arrDadosDataSets[0] = _.sortBy(arrDadosDataSets[0], 1);
                  }
                }

                if (grafico.MAX_REGISTROS > 0) {
                  arrDadosDataSets[0].splice(grafico.MAX_REGISTROS, arrDadosDataSets[0].length);
                }
                arrDadosDataSets[0].map((dataset) => {
                  dataset.splice(2, 1);
                });
                data.addRows(arrDadosDataSets[0]);
              }

              let view = new google.visualization.DataView(data);
              const options = {
                pieHole: tipoEhRosca ? 0.5 : 0,
                displayAnnotations: true,
                'backgroundColor': 'none',
                'width': '100%',
                'height': tamCard == '210' ? '350' : tamCard,
                'titleTextStyle': {
                  color: '#FFF',
                  fontSize: '15',
                  fontName: '"Arial"'
                },
                'hAxis': {
                  textStyle: {
                    color: $('html').hasClass('theme-light') ? '#000000' : '#ffffff'
                  },
                  title: tipoEhColuna ? grafico.EIXO : grafico.VALOR,
                  titleTextStyle: {
                    color: '#FFF',
                    fontSize: '15',
                    fontName: '"Arial"'
                  },
                  color: 'red'
                },
                // legend: 'none',
                legend: {
                  textStyle: {
                    color: $('html').hasClass('theme-light') ? '#000000' : '#ffffff'
                  }
                },
                'vAxis': {
                  format: formatoValor,
                  textStyle: {
                    color: $('html').hasClass('theme-light') ? '#000000' : '#ffffff'
                  },
                  title: tipoEhColuna ? grafico.VALOR : grafico.EIXO,
                  titleTextStyle: {
                    color: '#FFF',
                    fontSize: '15',
                    fontName: '"Arial"'
                  }
                },
                // colors: ['#1055A3'],
                annotations: {
                  textStyle: {
                    color: $('html').hasClass('theme-light') ? '#000000' : '#ffffff',
                  }
                }
              };

              if (tipoEhColuna) {
                var chart = new google.visualization.ColumnChart(document.getElementById(
                  `graf-${contadorGrafico}`));
              } else
              if (tipoEhBarra) {
                var chart = new google.visualization.BarChart(document.getElementById(
                  `graf-${contadorGrafico}`));
              } else
              if (tipoEhLinha) {
                var chart = new google.visualization.LineChart(document.getElementById(
                  `graf-${contadorGrafico}`));
              } else
              if (tipoEhPizza) {
                var chart = new google.visualization.PieChart(document.getElementById(
                  `graf-${contadorGrafico}`));
              } else
              if (tipoEhRosca) {
                var chart = new google.visualization.PieChart(document.getElementById(
                  `graf-${contadorGrafico}`));
              }
              chart.draw(view, options);
              $(window).resize(function() {
                chart.draw(view, options);
              });
            }
          }

          function retornaIdEstado(estado) {
            const lista = {
              "PR": "016",
              "SP": "025",
              "MG": "013",
              "ES": "008",
              "RJ": "019",
              "MS": "012",
              "SC": "024",
              "BA": "005",
              "RS": "021",
              "MT": "011",
              "GO": "009",
              "PA": "014",
              "RO": "022",
              "CE": "006",
              "PE": "017",
              "AC": "001",
              "MA": "010",
              "TO": "027",
              "DF": "007",
              "AM": "004",
              "AL": "002",
              "AP": "003",
              "PB": "015",
              "RR": "023",
              "PI": "018",
              "RN": "020",
              "SE": "026"
            }
            return lista[estado];
          }

          async function utilizaSyncFusionCharts(dados, grafico) {
            let minValue = 0;
            let maxValue = 0;
            const tamCard = grafico.TAM_CARD != '' ? grafico.TAM_CARD.trim() : '450';
            const listaDados = dados[0].map(
              dado => {
                return dado[0];
              });

            const dadosSeparados = {};

            listaDados.forEach(item => {
              const {
                CODIGO_ESTADO,
                CODIGO_CIDADE
              } = item;

              if (!dadosSeparados[CODIGO_ESTADO]) {
                dadosSeparados[CODIGO_ESTADO] = [];
              }

              dadosSeparados[CODIGO_ESTADO].push({
                sigla: CODIGO_ESTADO,
                id: CODIGO_CIDADE,
                value: item[grafico.VALOR]
              });
            });

            const listaEstadosCidade = [];
            const listaPorCidade = listaDados.reduce((agrupado, item) => {
              const cidadeExistente = agrupado.find((estado) => estado.sigla === item.CODIGO_ESTADO & estado.id === item.CODIGO_CIDADE);

              if (cidadeExistente) {
                cidadeExistente.value += item[grafico.VALOR];
              } else {
                agrupado.push({
                  sigla: item.CODIGO_ESTADO,
                  value: item[grafico.VALOR],
                  id: item.CODIGO_CIDADE
                });
              }
              return agrupado;
            }, []);

            const listaPorEstado = listaDados.reduce((agrupado, item) => {
              const estadoExistente = agrupado.find((estado) => estado.sigla === item.CODIGO_ESTADO);

              if (estadoExistente) {
                estadoExistente.value += item[grafico.VALOR];
              } else {
                agrupado.push({
                  sigla: item.CODIGO_ESTADO,
                  value: item[grafico.VALOR],
                  id: retornaIdEstado(item.CODIGO_ESTADO)
                });
              }

              return agrupado;
            }, []);

            listaPorEstado.map(result => {
              if (result.value > maxValue) {
                maxValue = result.value
              }
              return result;
            });

            for (let i = 0; i < Object.keys(dadosSeparados).length; i++) {
              const estado = Object.keys(dadosSeparados)[i];
              const cidades = dadosSeparados[estado];
              this['grafico' + grafico.ID + estado] = cidades;
            }

            // this['grafico'+ grafico.ID+'_objeto']= listaPorEstado;
            this['grafico' + grafico.ID + '_objeto'] = {
              id: grafico.ID,
              nome: grafico.NOME,
              min: minValue,
              max: maxValue,
              dados: listaPorEstado
            }

            var graficoChart = new FusionCharts({
              type: 'brazil',
              renderAt: document.getElementById(`graf-${contadorGrafico}`),
              width: '95%',
              height: tamCard == '210' ? '350' : tamCard,
              dataFormat: 'json',
              dataSource: {
                colorrange: {
                  "minvalue": "0",
                  "startlabel": "Poucas vendas",
                  "endlabel": "Muitas vendas",
                  "code": "#e44a00",
                  "gradient": "1",
                  "minvalue": minValue,
                  "maxValue": maxValue,
                  "color": [{
                    "maxvalue": minValue,
                    "displayvalue": "Araste para mostrar as maiores vendas",
                    "code": "#6baa01"
                  }, {
                    "maxvalue": maxValue,
                    "code": "#f8bd19"
                  }]
                },
                "chart": {
                  "theme": $('html').hasClass('theme-light') ? "fint" : "candy",
                  "canvasPadding": "30",
                  //"caption": "",                                                                   
                  //"subcaption": "",                                                                
                  "showMarkerLabels": "0",
                  "numberSuffix": "", //Changing connector hover color                               
                  "connectorHoverColor": "#f8bd19", //Changing connector hover thickness             
                  "connectorHoverThickness": "3", //Enabling entity hover effect                     
                  //Enabling marker hover effect                                                     
                  "showMarkerHoverEffect": "1", //Changing marker fill color on hover                
                  "markerFillHoverColor": "#cccccc",
                  "entityFillHoverColor": "#000",
                  "entityFillHoverAlpha": "30",
                  "showLabels": "1",
                  "formatNumberScale": "10",
                  "decimalSeparator": ",",
                  "thousandSeparator": "."
                },

                "data": listaPorEstado
              },
              "events": {
                "entityClick": function(evt, data) {
                  if (data.value) {
                    console.log(data.label, grafico.ID, grafico.NOME);
                    ShowMap(data.label, grafico.ID, grafico.NOME + ' - ' + data.label, minValue, maxValue);
                  }
                }
              }
            }).render();
          }

          async function utilizaApexCharts(dados, grafico) {
            const ordemDecrescente = grafico.TIPO_ORDENACAO == 0;
            const semOrdenacao = grafico.TIPO_ORDENACAO == -1;
            const tipoApresentacaoMonetario = grafico.TIPO_APRESENTACAO == 2;
            const tipoEhColuna = grafico.TIPO == 2;
            const tipoEhBarra = grafico.TIPO == 1;
            const tipoEhLinha = grafico.TIPO == 3;
            const tipoEhPizza = grafico.TIPO == 4;
            const tipoEhRosca = grafico.TIPO == 5;
            const tamCard = grafico.TAM_CARD != '' ? grafico.TAM_CARD.trim() : '350';

            let tipoGrafico = '';
            if (tipoEhColuna) {
              tipoGrafico = 'bar'
            } else if (tipoEhBarra) {
              tipoGrafico = 'bar'
            } else if (tipoEhLinha) {
              tipoGrafico = 'line'
            } else if (tipoEhPizza) {
              tipoGrafico = 'pie'
            } else if (tipoEhRosca) {
              tipoGrafico = 'donut'
            }

            const formatoValor = tipoApresentacaoMonetario ? 'currency' : 'decimal';
            let categories = [];
            let series = [];
            // google.charts.setOnLoadCallback(drawChart);


            const arrDadosDataSets = [];
            const data = new google.visualization.DataTable();
            for (let i = 0; i < dados.length; i++) {
              const regAgrupados = [];
              const dataset = dados[i]; // numero de datasets
              for (let y = 0; y < dataset.length; y++) {
                let totGrupo = 0;
                const registros = dataset[y]; // array de registros por dataset
                for (let z = 0; z < registros.length; z++) {
                  totGrupo += registros[z][grafico.VALOR];
                  if (z == registros.length - 1) {
                    regAgrupados.push([String(registros[z][grafico.EIXO]), totGrupo, registros[z][grafico.CAMPO_ORDENACAO]]);
                  }
                }
              }
              arrDadosDataSets.push(regAgrupados);
            }


            for (let i = 0; i < arrDadosDataSets.length; i++) {
              series.push({
                name: grafico.DATASET_INFO[i],
                data: [],
                cor: ''
              });
            }


            if (arrDadosDataSets.length > 1) {
              const arrTeste = await ajustaDadosDataSetMultiSerie(arrDadosDataSets, grafico.DATASET_INFO.length);
              let novoArray = [];
              const arrDadosFinais = [];

              // data.addColumn('string', grafico.EIXO);

              novoArray = arrTeste;

              for (let i = 0; i < novoArray.length; i++) {
                const dataNovoArray = novoArray[i];
                const arrDadosAtuais = [];
                for (let y = 0; y < dataNovoArray.length; y++) {
                  const registro = dataNovoArray[y];
                  for (let z = 0; z < registro.length; z++) {
                    if (!((y != 0) && (z == 0))) { //nao repetir a legenda do dataset...
                      const dadoReg = registro[z];
                      arrDadosAtuais.push(dadoReg);
                    }
                  }
                }
                while (arrDadosAtuais.length - 1 < grafico.DATASET_INFO.length) {
                  arrDadosAtuais.push(0);
                }
                arrDadosFinais.push(arrDadosAtuais);
              }
              for (let i = 0; i < arrDadosFinais.length; i++) {
                categories.push(arrDadosFinais[i][0]);

                for (let y = 1; y < arrDadosFinais[i].length; y++) {
                  series[y - 1].data.push(parseFloat(arrDadosFinais[i][y]).toFixed(2));
                }
              }
            } else {
              // data.addColumn('string', grafico.EIXO);
              // data.addColumn('number', grafico.VALOR);
              if (tipoEhColuna || tipoEhBarra || tipoEhLinha) {
                if (!semOrdenacao && ordemDecrescente) {
                  arrDadosDataSets[0] = _.sortBy(arrDadosDataSets[0], 1).reverse();
                } else if (!semOrdenacao) {
                  arrDadosDataSets[0] = _.sortBy(arrDadosDataSets[0], 1);
                }
              }

              if (grafico.MAX_REGISTROS > 0) {
                arrDadosDataSets[0].splice(grafico.MAX_REGISTROS, arrDadosDataSets[0].length);
              }
              arrDadosDataSets[0].map((dataset) => {
                dataset.splice(2, 1);
              });
              // data.addRows(arrDadosDataSets[0]);
              for (let i = 0; i < arrDadosDataSets[0].length; i++) {
                categories.push(arrDadosDataSets[0][i][0]);
                series[0].data.push(parseFloat(arrDadosDataSets[0][i][1]).toFixed(2));
              }
            }

            let colors = [];

            dados.map(item => {
              if (item.cor != '') {
                colors.push(item.cor);
              }
            });

            if (colors.length == 0) {
              colors = ["#940000", "#00478f"];
              if (grafico.DATASET.split(',').length > 1) {
                const cor1 = arrDados.findIndex(gf => gf.id == Number(grafico.DATASET.split(',')[0].trim()));
                const cor2 = arrDados.findIndex(gf => gf.id == Number(grafico.DATASET.split(',')[1].trim()));

                if ((cor1 != -1) && (arrDados[cor1].cor != '')) {
                  colors[0] = arrDados[cor1].cor
                };
                if ((cor2 != -1) && (arrDados[cor2].cor != '')) {
                  colors[1] = arrDados[cor2].cor
                };
              } else {
                const corGrafico = arrDados.findIndex(gf => gf.id == Number(grafico.DATASET.trim()));
                if ((corGrafico != -1) && arrDados[corGrafico].cor != '') {
                  colors[0] = arrDados[corGrafico].cor;
                }
              }
            }

            const deveMostrarLabel = ((arrDadosDataSets.map(dataset => dataset.length).filter(data => data > 30).length == 0) || (tipoEhLinha));
            let options = '';
            if ((tipoEhPizza) || (tipoEhRosca)) {
              options = {
                series: series[0].data.map(serie => Number(serie)),
                chart: {
                  type: tipoGrafico,
                  width: '100%'
                },
                labels: categories,
                plotOptions: {
                  pie: {
                    size: '100%'
                  }
                }

                // responsive: [{
                //   breakpoint: 480,
                //   options: {
                //     chart: {
                //       width: 400
                //     },
                //     legend: {
                //       position: 'bottom'
                //     }
                //   }
                // }]
              };

            } else {
              options = {
                series: series,
                colors: colors,
                stroke: {
                  width: tipoEhColuna || tipoEhBarra ? 2 : 5
                },
                fill: {
                  type: 'gradient',
                  gradient: {
                    shade: 'dark',
                    type: 'vertical',
                    shadeIntensity: tipoEhColuna || tipoEhBarra ? 0.5 : 0,
                    inverseColors: false,
                    opacityFrom: 1,
                    opacityTo: $('html').hasClass('theme-light') ? 1 : 0.8,
                    stops: [0, 100]
                  }
                },
                grid: {
                  show: true,
                  strokeDashArray: 0,
                  borderColor: '#cfcfcf60',
                },
                chart: {
                  type: tipoGrafico,
                  height: tamCard == '210' ? '350' : tamCard,
                  zoom: {
                    enabled: true,
                    type: 'x',
                    autoScaleYaxis: false,
                    zoomedArea: {
                      fill: {
                        color: '#90CAF9',
                        opacity: 0.4
                      },
                      stroke: {
                        color: '#0D47A1',
                        opacity: 0.4,
                        width: 1
                      }
                    }
                  },
                  animations: {
                    enabled: true,
                    easing: 'easeinout',
                    speed: 1200,
                    animateGradually: {
                      enabled: true,
                      delay: 150
                    },
                    dynamicAnimation: {
                      enabled: true,
                      speed: 350
                    }
                  },
                },
                plotOptions: {
                  bar: {
                    horizontal: !tipoEhColuna,
                    borderRadius: 4,
                    dataLabels: {
                      orientation: tipoEhColuna ? 'vertical' : 'horizontal',
                      position: 'center' // bottom/center/top
                    }
                  }
                },
                dataLabels: {
                  enabled: deveMostrarLabel,
                  // dropShadow: {
                  //   enabled: true
                  // },
                  formatter: function(val) {
                    const tipoApresentacaoDecimal = grafico.TIPO_APRESENTACAO == 1;
                    const tipoApresentacaoMonetario = grafico.TIPO_APRESENTACAO == 2;
                    if (tipoApresentacaoDecimal) {
                      return new Intl.NumberFormat('pt-BR').format(val);
                    } else if (tipoApresentacaoMonetario) {
                      return new Intl.NumberFormat('pt-BR', {
                        style: 'currency',
                        currency: 'BRL'
                      }).format(val);
                    } else {
                      return val;
                    }
                  },
                  style: {
                    fontSize: '12px',
                    fontFamily: 'Helvetica, Arial, sans-serif',
                    colors: [tipoEhColuna || tipoEhBarra ? '#fff' : '#000000']
                  },
                },
                xaxis: {
                  categories: categories,
                  tickPlacement: 'between',
                },
                tooltip: {
                  y: {
                    formatter: function(val) {
                      const tipoApresentacaoDecimal = grafico.TIPO_APRESENTACAO == 1;
                      const tipoApresentacaoMonetario = grafico.TIPO_APRESENTACAO == 2;
                      if (tipoApresentacaoDecimal) {
                        return new Intl.NumberFormat('pt-BR').format(val);
                      } else if (tipoApresentacaoMonetario) {
                        return new Intl.NumberFormat('pt-BR', {
                          style: 'currency',
                          currency: 'BRL'
                        }).format(val);
                      } else {
                        return val;
                      }
                    }
                  }
                },
                yaxis: {
                  labels: {
                    show: true,
                    formatter: function(val) {
                      return val;
                    }
                  }
                },
              };

              if (grafico.VALOR_FIXO_META ?? 0 > 0) {
                options.annotations = {
                  yaxis: [{
                    y: grafico.VALOR_FIXO_META,
                    borderColor: '#7d7d7d',
                    strokeDashArray: 6,
                    label: {
                      text: grafico.VALOR_FIXO_META.toLocaleString('pt-BR', {
                        minimumFractionDigits: 2,
                        maximumFractionDigits: 2
                      }),
                      textAnchor: 'end',
                      position: 'right',
                      offsetX: 0,
                      offsetY: 0,
                      borderColor: 'transparent',
                      style: {
                        background: 'transparent',
                        color: '#fff',
                        fontSize: '12px',
                        fontWeight: 600,
                        padding: {
                          left: 6,
                          right: 6,
                          top: 3,
                          bottom: 3
                        }
                      }
                    }
                  }]
                }

                options.tooltip = {
                  shared: true,
                  intersect: false,
                  custom: function({
                    series,
                    dataPointIndex,
                    w
                  }) {
                    const categoria = categories[dataPointIndex];

                    const cores = colors;
                    const nomesSeries = series.map(s => s.name);

                    const rows = nomesSeries.map((nome, index) => {
                      const valor = series[index][dataPointIndex];
                      const nomeCerto = grafico.DATASET_INFO[index];

                      return `
                    <div class="tt-row">
                      <div class="tt-left">
                        <span class="dot" style="background:${cores[index]}"></span>
                        <span>${nomeCerto}</span>
                      </div>
                      <span class="value">${valor ?? '-'}</span>
                    </div>
                  `;
                    }).join('');

                    return `
                <div class="custom-tooltip">
                  <div class="tt-title">${categoria}</div>

                  ${rows}

                  <div class="tt-row">
                    <div class="tt-left">
                      <span class="meta-dot"></span>
                      <span>Meta</span>
                    </div>
                    <span class="value">${grafico.VALOR_FIXO_META}</span>
                  </div>
                </div>
              `;
                  }
                }

              }
            }

            $(`#graf-${contadorGrafico}`).html('');

            const chart = new ApexCharts(document.getElementById(`graf-${contadorGrafico}`), options);
            chart.render();
            $(`#graf-${contadorGrafico}`).css('min-height', 'auto')
          }


          async function criaGrafico(grafico) {
            const TOTAL_GRAFICO_NAO_UTILIZADO = 0;
            const dadosGraf = await montaDadosGrafico(grafico);
            const tam = await converteProporcaoEmTamanhoBootstrap(grafico.PROPORCAO);
            await incrementaContador();
            await insereGraficoNoPainel(TOTAL_GRAFICO_NAO_UTILIZADO, grafico, tam);
            if ([4, 5].includes(grafico.TIPO)) {
              await utilizaGoogleCharts(dadosGraf, grafico);
            } else if (grafico.TIPO == 7) {
              await utilizaSyncFusionCharts(dadosGraf, grafico);
            } else if (grafico.TIPO != 6) {
              await utilizaApexCharts(dadosGraf, grafico);
            } else {
              await criaGrid(dadosGraf, grafico);
            }
          }


          async function criaGrid(dados, grafico) {
            const ordemDecrescente = grafico.TIPO_ORDENACAO == 0;
            const semOrdenacao = grafico.TIPO_ORDENACAO == -1;
            const tipoApresentacaoInteiro = grafico.TIPO_APRESENTACAO == 0;
            const tipoApresentacaoDecimal = grafico.TIPO_APRESENTACAO == 1;
            const tipoApresentacaoMonetario = grafico.TIPO_APRESENTACAO == 2;
            const formatoValor = tipoApresentacaoMonetario ? 'currency' : 'decimal';
            const local = $(`#graf-${contadorGrafico}`);
            const keys = grafico.EIXO.replaceAll(' ', '').split(',')
            const dataSetCols = [];
            const tamFonte = grafico.TAM_FONTE != '' ? grafico.TAM_FONTE.trim() + 'px' : '15px';
            const tamCard = grafico.TAM_CARD != '' ? grafico.TAM_CARD.trim() + 'px' : '210px';

            for (var k in keys) {
              dataSetCols.push({
                'title': keys[k].toUpperCase(),
                'data': keys[k]
              });
            }
            local.html(`<div style="font-size: ${tamFonte}; text-align: center" class="table-responsive p-2"><table width="100%" style="width: 100%" class="table table-sm" id="tabela-${contadorGrafico}"><thead></thead><tbody></tbody></table></div>`)
            criaDataTablePadrao(`#tabela-${contadorGrafico}`, false, false, false, false, true, true, tamCard, dados[0][0], dataSetCols, []);
            $(`#tabela-${contadorGrafico}`).DataTable().columns.adjust().draw(false);

          }

          async function somaRegistros(dados, grafico) {
            let totGrupo = 0;
            for (let i = 0; i < dados.length; i++) {
              const grupos = dados[i];
              for (let y = 0; y < grupos.length; y++) {
                const registro = grupos[y];
                totGrupo += registro[grafico.VALOR];
              }
            }
            return totGrupo;
          }

          async function mediaRegistros(dados, grafico) {
            let totGrupo = 0;
            for (let i = 0; i < dados.length; i++) {
              const grupos = dados[i];
              for (let y = 0; y < grupos.length; y++) {
                const registro = grupos[y];
                totGrupo += registro[grafico.VALOR];
              }
            }
            return totGrupo / dados.length;
          }

          async function maximoRegistros(dados, grafico) {
            let totGrupo = 0;
            for (let i = 0; i < dados.length; i++) {
              const grupos = dados[i];
              for (let y = 0; y < grupos.length; y++) {
                const registro = grupos[y];
                if (totGrupo < registro[grafico.VALOR]) {
                  totGrupo = registro[grafico.VALOR];
                }
              }
            }
            return totGrupo;
          }

          async function minimoRegistros(dados, grafico) {
            let totGrupo = 0;
            for (let i = 0; i < dados.length; i++) {
              const grupos = dados[i];
              for (let y = 0; y < grupos.length; y++) {
                const registro = grupos[y];
                if (totGrupo == 0 || totGrupo > registro[grafico.VALOR]) {
                  totGrupo = registro[grafico.VALOR];
                }
              }
            }
            return totGrupo;
          }

          async function contaRegistros(grafico) {
            const indice = parseInt(grafico.DATASET.split(', ')[0]);
            return arrDados.find(dado => dado.id == indice).data.length;
          }

          async function retornaHtmlCard(total, grafico, tam) {
            const tipoApresentacaoInteiro = grafico.TIPO_APRESENTACAO == 0;
            const tipoApresentacaoDecimal = grafico.TIPO_APRESENTACAO == 1;
            const tipoApresentacaoMonetario = grafico.TIPO_APRESENTACAO == 2;
            const tamCard = grafico.TAM_CARD != '' ? grafico.TAM_CARD.trim() : '350';

            let valorFormatado;
            if (tipoApresentacaoInteiro) {
              valorFormatado = parseInt(total)
            } else if (tipoApresentacaoDecimal) {
              valorFormatado = total.toLocaleString('pt-BR')
            } else if (tipoApresentacaoMonetario) {
              valorFormatado = 'R$ ' + total.toLocaleString('pt-BR')
            } else {
              valorFormatado = total;
            }

            const textoValor = (grafico.TEXTO_VALOR != '' && grafico.TEXTO_VALOR != '<p><br></p>') ? grafico.TEXTO_VALOR.replace('#VALOR', valorFormatado) : valorFormatado;

            let background = '';

            const corGradiente = grafico.GRADIENTE != '' ? grafico.GRADIENTE : '';
            if (corGradiente) {
              background = `linear-gradient(90deg, ${grafico.GRADIENTE.split(' ')[0]} 0%, ${grafico.GRADIENTE.split(' ')[1]} 100%);`;
            } else {
              background = grafico.COR;
            }

            const html = `<div class="col-lg-${tam}" title="${grafico.HINT}" col-12 animate__animated animate__fadeIn" id="card-${contadorGrafico}" style="color: var(--white) !important;">
                        <div class="small-box ${(background) ? '' : 'bg-info'}" ${background ? `style="background: ${background} ${tamCard != '350' ? ';min-height: '+tamCard+'px;display: flex; flex-direction: column' : ''}"` : `${tamCard != '350' ? 'min-height: '+tamCard+'px;display: flex; flex-direction: column' : ''}`}>
                          <div class="inner" style="flex: 1">
                            <h3>${textoValor}</h3>
                            <p>${grafico.NOME}</p>
                          </div>
                          <div class="icon">
                            <i class="${grafico.ICONE}"></i>
                          </div>
                          <a href="" id="info-${contadorGrafico}" class="small-box-footer">Mais Informações 
                            <i class="fas fa-arrow-circle-right"></i>
                          </a>
                        </div>
                      </div>`;
            return html;
          }

          async function retornaHtmlGraficoBarraEColuna(total, grafico, tam) {
            const styleGraficoMapa = grafico.TIPO == '7' ? `display: flex; justify-content: center;` : '';
            const html = `<div class="col-lg-${tam} col-12 animate__animated animate__fadeIn">
                            <div class="card">
                              <div class="card-header bg-info">
                                <h3 class="card-title">${grafico.NOME}</h3>

                                <div class="card-tools">
                                  <button type="button" class="btn btn-tool" data-card-widget="collapse"><i class="fas fa-minus"></i>
                                  </button>
                                </div>
                              </div>
                              <div class="card-body">
                                <div id="graf-${contadorGrafico}" style="${styleGraficoMapa}">
                                </div>
                              </div>
                            </div>
                          </div> `;
            return html;
          }

          async function MostraModalInfo(grafico, dados) {
            var keys = Object.keys(dados[0]);
            let dataSetCols = [];
            for (var k in keys) {
              dataSetCols.push({
                'title': keys[k],
                'data': keys[k]
              });
            }
            const htmlTable =
              `<table width="100%" style="width:100%" id="table-info-card" class="table table-sm table-condensed table-select table-hover"></table>`
            $('#modal-info-table').html(htmlTable);
            $('#modal-info-title').html(grafico.NOME);
            $('#table-info-card').DataTable({
              paging: true,
              filter: false,
              info: true,
              order: true,
              destroy: true,
              autowidth: true,
              dom: 'Bfrtip',
              buttons: [{
                  "extend": 'excel',
                  "text": 'Exportar Excel',
                  "className": 'btn btn-primary btn-sm btn-sisp',
                  "title": `Dashboard - ${grafico.NOME}`
                },
                {
                  alignment: "center",
                  "extend": 'pdf',
                  "text": 'Exportar PDF',
                  "className": 'btn btn-secondary btn-sm btn-sisp',
                  customize: function(doc) {
                    doc.styles.tableBodyEven.alignment = 'center';
                    doc.styles.tableBodyOdd.alignment = 'center';
                    doc.content[1].table.widths =
                      Array(doc.content[1].table.body[0].length + 1).join('*').split('');
                  },
                  "title": `Dashboard - ${grafico.NOME}`
                }
              ],
              "language": {
                "sEmptyTable": "Nenhum registro encontrado",
                "sInfo": "_TOTAL_ registros",
                "sInfoEmpty": " 0 registros",
                "sInfoFiltered": "(Filtrados de _MAX_ registros)",
                "sInfoPostFix": "",
                "sInfoThousands": ".",
                "sLengthMenu": "_MENU_ resultados",
                "sLoadingRecords": "Carregando...",
                "sProcessing": "Processando...",
                "sZeroRecords": "Nenhum registro encontrado",
                "sSearch": "Pesquisar (geral): ",
                "oPaginate": {
                  "sNext": "Próximo",
                  "sPrevious": "Anterior",
                  "sFirst": "Primeiro",
                  "sLast": "Último"
                },
                "oAria": {
                  "sSortAscending": ": Ordenar colunas de forma ascendente",
                  "sSortDescending": ": Ordenar colunas de forma descendente"
                }
              },
              "data": dados,
              "columns": dataSetCols
            });

            $('#modal-info').modal('show');
            $('#table-info-card').DataTable().columns.adjust().draw(false);

          }

          async function insereGraficoNoPainel(total, grafico, tam) {
            const [graficoTipoCard, graficoTipoBarra, graficoTipoColuna] = [grafico.TIPO == 0, grafico.TIPO == 1,
              grafico.TIPO == 2
            ];
            const html = graficoTipoCard ? await retornaHtmlCard(total, grafico, tam) :
              await retornaHtmlGraficoBarraEColuna(total, grafico, tam);
            $('#conteudo').append(html);
            if (graficoTipoCard) {
              $(`#info-${contadorGrafico}`).on('click', async function() {
                window.event.preventDefault();
                const id = parseInt($(this).attr('id').split('-')[1]);
                const grafico = arrGraficos[id - 1];
                const dados = arrDados.find(dado => dado.id == grafico.DATASET.split(', ')[0]).data;
                await MostraModalInfo(grafico, dados)
              });
            }
          }

          async function criaCard(grafico) {
            const [tipoValorSoma, tipoValorMedia, tipoValorMaximo, tipoValorMinimo, tipoValorContagem,
              tipoValorContagemDistinta
            ] = [grafico.TIPO_VALOR == 0, grafico.TIPO_VALOR == 1, grafico.TIPO_VALOR == 2, grafico.TIPO_VALOR ==
              3, grafico.TIPO_VALOR == 4, grafico.TIPO_VALOR == 5
            ];
            const dadosGraf = await montaDadosGrafico(grafico);
            await incrementaContador();
            const tam = await converteProporcaoEmTamanhoBootstrap(grafico.PROPORCAO);
            let total = 0;
            if (tipoValorSoma) {
              total = await somaRegistros(dadosGraf[0], grafico);
            } else
            if (tipoValorContagem || tipoValorContagemDistinta) {
              total = await contaRegistros(grafico);
            } else
            if (tipoValorMedia) {
              total = await mediaRegistros(dadosGraf[0], grafico);
            } else
            if (tipoValorMaximo) {
              total = await maximoRegistros(dadosGraf[0], grafico);
            } else
            if (tipoValorMinimo) {
              total = await minimoRegistros(dadosGraf[0], grafico);
            }
            await insereGraficoNoPainel(total, grafico, tam);
          }

          async function rotinaValidarSQL(sql) {
            const _url = `/sisplan/funcoes/v1/EditorSQL?`;
            try {
              try {
                var response = await requisicao('POST', _url, '',
                  `JSON=${encodeURIComponent(sql)}`, null);

                if (!response) {
                  return;
                }

                var jsonStr = await response.json();
                if (response.status === 400) {
                  msgErro(jsonStr.mensagem);
                  return;
                } else
                if (response.status === 202) {
                  return [];
                }

                return jsonStr;
              } catch (error) {
                console.error(error);
                msgErro('Erro ao validar sql.');
              }
            } finally {}
          }

          async function criaAviso(sMensagem) {
            if ($('#card-carregando').hasClass('d-none')) {
              await $('#card-carregando').removeClass('d-none');
            }
            await $('#card-carregando h5').html(sMensagem);

          }

          async function destroiAviso() {
            await $('#card-carregando').addClass('d-none');
            await $('#card-carregando h5').html('');
          }

          async function montaDadosGrafico(grafico) {
            const tipoEhCard = grafico.tipo == '0';
            const {
              TIPO: tipo,
              EIXO: eixo,
              VALOR: valor,
              CAMPO_ORDENACAO: ordenacao
            } = grafico;
            const arrDataSets = grafico.DATASET.split(', ');
            let arrRetorno = [];
            arrDataSets.forEach(dataset => {
              const arrayDados = arrDados.find(dado => dado.id == dataset).data;
              let dadosNovos = [];
              dadosNovos = _.sortBy(arrayDados, eixo);
              if (tipoEhCard) {
                dadosNovos = _.groupBy(dadosNovos, ''); //agrupa pelo indice do EIXO
              } else {
                dadosNovos = _.groupBy(dadosNovos, eixo); //agrupa pelo indice do EIXO
              }
              dadosNovos = _.map(dadosNovos); //mapea o objeto como array
              dadosNovos.cor = arrDados.find(dado => dado.id == dataset).cor;
              arrRetorno.push(dadosNovos);
            });
            return arrRetorno;
          }

          try {
            await buscaDashboard();
            await buscaFiltros();
            const todosFiltrosPreenchidos = filtros.filter((filtro) => {
              if ($('#' + filtro.component).val() == '') {
                return true;
              } else {
                return false;
              }
            }).length == 0;
            if ((filtros.length == 0) || (todosFiltrosPreenchidos)) {
              await criaAviso('Carregando Dados');
              await buscaDatasets();
              await buscaGraficos();
            }

          } finally {
            await destroiAviso();
          }
        });
      </script>
</body>

</html>