{#
/**
 * Copyright (C) 2022 Xibo Signage Ltd
 *
 * Xibo - Digital Signage - http://www.xibo.org.uk
 *
 * This file is part of Xibo.
 *
 * Xibo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * Xibo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Xibo.  If not, see <http://www.gnu.org/licenses/>.
 */
#}
{% import "inline.twig" as inline %}
{% set gridId = random() %}
<script type="text/javascript" nonce="{{ cspNonce }}">
  $(function() {
    $('#connectors').on('connectors.loaded', function() {
      var $sspConnector = $('#connectors').find('div[data-connector-class-name-last="XiboSspConnector"]');
      var $button = $('<button class="btn btn-info" role="button">{% trans "Activity Report" %}</button>');
      $button.on('click', function() {
        sspActivityDialogOpen($sspConnector);
      });
      $sspConnector.find('.card-footer').append($button);
    });
  });

  window.sspFormOpen = function(dialog) {
    // CMS Url
    var $cmsUrl = dialog.find('input[name="cmsUrl"]');
    if ($cmsUrl.val() === '') {
      $cmsUrl.val(window.location.origin || null);
    }

    // Share of voice
    var $shareOfVoice = dialog.find('.share-of-voice-control');
    $shareOfVoice.on('change paste keyup', function() {
      dialog.find($(this).data('partner')).val(((100 * $(this).val()) / 3600).toFixed(2));
    }).trigger('change');

    $shareOfVoice.each(function(index, element) {
      dialog.find($(element).data('partner')).on('change paste keyup', function() {
        $(element).val(Math.round((3600 * $(this).val()) / 100));
      });
    });
  };

  window.sspActivityDialogOpen = function($sspConnector) {
    bootbox.hideAll();
    // Put the template into a modal.
    var template = Handlebars.compile($('#connector-ssp-activity').html());
    var dialog = bootbox.dialog({
      message: template({}),
      title: '{{ "Activity Report"|trans }}',
      animate: false,
      size: 'xl',
      onShown: function(e) {
        $.ajax({
          url: $sspConnector.data('proxyUrl').replace(':method', 'getAvailablePartnersFilter'),
          success: function(result) {
            if (result) {
              const $form = $('#activity-log-filters');
              const $partnerId = $form.find('select[name=partnerId]');

              $.each(result, function(partnerKey, available) {
                $partnerId.append($('<option>', {
                  id: partnerKey,
                  text: available.name,
                  value : partnerKey
                }));
              });
            }
          }
        });
      }
    });

    XiboInitialise('#{{ gridId }}');

    dialog.closest('.modal').addClass('modal-big');

    // Initialize summary filter
    let filter;

    // Make a datatable
    var table;
    var chart;

    // Disable the Apply button on initialization
    let applyBtn = dialog.find('a[data-apply-button="true"]').addClass('disabled');
    let displaySelect = dialog.find('select[name="displayId"]');
    let formError = $('.form-error').hide();

    // Enable the applyBtn when there's a display selected
    displaySelect.on('change', function () {
      let value = $(this).val();

      applyBtn.toggleClass('disabled', !value);

      $('.alert-danger').toggle(!value);
    });

    // Find the apply button
    applyBtn.on('click', function(e) {
      if ($(this).hasClass('disabled')) {
        e.preventDefault();
        return;
      }

      $(this).addClass('disabled').append('<span class="saving fa fa-cog fa-spin p-1"></span>');

      if (!table) {
        initTable();
      } else {
        table.ajax.reload(function(json) {
          let filteredData = filterData(json.data, filter);

          drawSummaryTable(filteredData, filter);
        }, true);
      }
    });

    // Watch for filter option changes in Summary tab
    dialog.find('select[name="campaignFilter"]').on('change', function(e) {
      if (displaySelect.val()) {
        table.ajax.reload(function(json) {
          filter = $(e.target).val();
          let filteredData = filterData(json.data, filter);

          drawSummaryTable(filteredData, filter);
        }, true);
      }
    });

    // Parse activity log summary according to filter selected
    function filterData(summaryData, filter='hour') {
      let filterOption = '';

      // Group the data according the filter selected
      let groups = summaryData.reduce((group, item) => {
        let hourKey = `${moment(item.scheduledAt).format('YYYY-MM-DD HH')}:00`;
        let errorKey = item.errorCode || '';

        if (filter === 'hour') {
          filterOption = hourKey;
        } else if (filter === 'errorCode') {
          filterOption = errorKey;
        } else {
          filterOption = `${hourKey} - ${errorKey}`;
        }

        if (!group[filterOption]) {
          group[filterOption] = [];
        }

        group[filterOption].push({key: filterOption, ...item});

        return group;
      }, {});

      const groupKeys = Object.keys(groups);

      // Aggregate the data
      let data = groupKeys.map(key => {
        return groups[key].reduce((acc, {key, campaignId, scheduledAt, displayId, errors, isPlayed, isErrored, impressions, impressionActual, errorCode}) => {
          acc['key'] = String(key);
          acc['errorCount'] = errors + (acc['errorCount'] || 0);
          acc['playCount'] = (isPlayed ? 1 : 0) + (acc['playCount'] || 0);
          acc['missesCount'] = (!isPlayed && !isErrored ? 1 : 0) + (acc['missesCount'] || 0);
          acc['impressions'] = impressions + (acc['impressions'] || 0);
          acc['impressionActual'] = impressionActual + (acc['impressionActual'] || 0);
          acc['campaignId'] = campaignId;
          acc['date'] = moment(scheduledAt).format('MM-DD-YYYY');
          acc['time'] = `${moment(scheduledAt).format('HH')}:00`;
          acc['errorCode'] = errorCode;

          return acc;
        }, {});
      })

      // Get new data stats
      let stats = {
        totalErrorCount: 0,
        totalPlayCount: 0,
        totalMissCount: 0,
        totalImpressions: 0,
        impressionActual: 0
      }

      $.each(data, function(index, el) {
        stats.totalErrorCount += el.errorCount;
        stats.totalPlayCount += el.playCount;
        stats.totalMissCount += el.missesCount;
        stats.totalImpressions += el.impressions;
        stats.impressionActual += el.impressionActual;
      });

      return {
        data: data.sort((a,b) => a.key.replace(/-|\s/g,"") - b.key.replace(/-|\s/g,"")),
        stats: stats
      }
    }

    function initTable() {
      table = $('#ssp-activity').DataTable({
        language: dataTablesLanguage,
        dom: dataTablesTemplate,
        serverSide: false,
        stateSave: false,
        responsive: true,
        filter: false,
        searchDelay: 3000,
        order: [[ 0, 'asc']],
        ajax: {
          url: $sspConnector.data('proxyUrl').replace(':method', 'activity'),
          data: function (d) {
            $.extend(d, $('#ssp-activity').closest('.XiboGrid').find('.FilterDiv form').serializeObject());
          },
          dataSrc: function (json) {
            if (json.success === false) {
              formError.show().text(json.message);

              return [];
            }

            formError.hide().text('');
            return json.data || [];
          }
        },
        columns: [
          {
            data: 'scheduledAt',
            responsivePriority: 1,
            render: function(data, type) {
              if (type !== 'display' && type !== 'export' || data == null) {
                return data;
              }
              return moment(data).format(jsDateFormat);
            },
          },
          { data: 'campaignId', responsivePriority: 1 },
          { data: 'displayId', responsivePriority: 1 },
          { data: 'isPlayed', responsivePriority: 1 },
          { data: 'isErrored', responsivePriority: 1 },
          { data: 'impressions', responsivePriority: 2 },
          {
            data: 'impressionDate',
            responsivePriority: 10,
            render: function(data, type) {
              if (type !== 'display' && type !== 'export' || data == null) {
                return data;
              }
              return moment(data).format(jsDateFormat);
            },
          },
          { data: 'impressionActual', responsivePriority: 10 },
          { data: 'errors', responsivePriority: 10 },
          {
            data: 'errorDate',
            responsivePriority: 10,
            render: function(data, type) {
              if (type !== 'display' && type !== 'export' || data == null) {
                return data;
              }
              return moment(data).format(jsDateFormat);
            },
          },
          { data: 'errorCode', responsivePriority: 10 },
        ],

        initComplete: function(settings, json) {
          if (json && json.data) {
            let filteredData = filterData(json.data, filter);
            drawSummaryTable(filteredData, filter);
          }
        },

        footerCallback: function(row, data, start, end, display) {
          var json = this.api().ajax.json();
          if (json && json.stats) {
            $(this.api().column(0).footer()).html(json.stats.scheduled || 0);
            $(this.api().column(3).footer()).html(json.stats.played || 0);
            $(this.api().column(4).footer()).html(json.stats.errored || 0);
            $(this.api().column(5).footer()).html(json.stats.actualImpressions || 0);
          }
        },

        drawCallback: function(settings) {
          setTimeout(function() {
            dialog.find('a[data-apply-button="true"]')
              .removeClass('disabled')
              .find('.saving').remove();
          }, 300);
        },
      });

      table.on('draw', dataTableDraw);
      table.on('processing.dt', dataTableProcessing);
      dataTableAddButtons(table, $('#ssp-activity_wrapper').find('.dataTables_buttons'));
    }

    function drawSummaryTable(filteredData, filter='hour') {
      let summaryTable = $('#ssp-activity-summary').dataTable({
        "bDestroy": true,
        data: filteredData.data,
        columns: [
          { data: 'date', responsivePriority: 1 },
          { data: 'time', responsivePriority: 1 },
          { data: 'campaignId', responsivePriority: 1 },
          { data: 'playCount', responsivePriority: 1 },
          { data: 'errorCount', responsivePriority: 1 },
          { data: 'missesCount', responsivePriority: 1 },
          { data: 'impressions', responsivePriority: 2 },
          { data: 'impressionActual', responsivePriority: 10 },
          { data: 'errorCode', responsivePriority: 1 },
        ],

        initComplete: function () {
          if (filter === 'hour' ) {
            // Hide Error Code column
            $(this.api().column(8).visible(false));
          } else if (filter === 'errorCode') {
            // Hide date and hour
            $(this.api().column(0).visible(false));
            $(this.api().column(1).visible(false));
          }

          drawSummaryChart(filteredData.stats);
        },

        footerCallback: function(row, data, start, end, display) {
            var json = filteredData.stats;
            if (filteredData) {
                $(this.api().column(3).footer()).html(json.totalPlayCount || 0);
                $(this.api().column(4).footer()).html(json.totalErrorCount || 0);
                $(this.api().column(5).footer()).html(json.totalMissCount || 0);
                $(this.api().column(6).footer()).html(json.totalImpressions || 0);
                $(this.api().column(7).footer()).html(json.impressionActual || 0);
            }
        },
      });

      // Render the summary table
      summaryTable.on('draw', dataTableDraw);
      summaryTable.on('processing.dt', dataTableProcessing);
    }

    // Renders the chart data
    function drawSummaryChart(data) {
      if (chart !== undefined && chart !== null) {
        chart.destroy();
      }

      // Organise the rows into datasets for the chart
      let totalSize = data.totalErrorCount + data.totalPlayCount + data.totalMissCount;
      let chartData = {
          userData: [getPercentage(data.totalErrorCount), getPercentage(data.totalPlayCount), getPercentage(data.totalMissCount)],
          userLabels: ['Errors', 'Plays', 'Misses'],
          colours: ['red', 'green', 'blue']
      }

      function getPercentage(data) {
        return ((data/totalSize)*100).toFixed(2);
      }

      // Create the pie chart
      chart = new Chart($("#canvas"), {
        type: 'pie',
        data: {
          datasets: [{
            data: chartData.userData,
            backgroundColor: chartData.colours
          }],
          labels: chartData.userLabels
        },
        options: {
          maintainAspectRatio: true
        }
      });
    }
  };
</script>
<script type="text/x-handlebars-template" id="connector-ssp-activity">
  <div class="XiboGrid" id="{{ gridId }}" data-grid-name="connector-ssp-activity-log">
      <div class="XiboFilterCustom card bg-light mb-3">
          <div class="FilterDiv card-body" id="connector-ssp-activity-log">
              <form id="activity-log-filters" class="form-inline">
                  {% set title %}{% trans "From Date" %}{% endset %}
                  {{ inline.dateTime("activityFromDt", title, 'now'|date_modify('today')|date("Y-m-d H:i:s"), "", "activity-from-dt", "", "") }}

                  {% set title %}{% trans "To Date" %}{% endset %}
                  {{ inline.dateTime("activityToDt", title, 'tomorrow'|date_modify('-1 minute')|date("Y-m-d H:i:s"), "", "activity-to-dt", "", "") }}

                  {% set title %}{% trans "Display" %}<span class="text-danger">*</span>{% endset %}
                  {% set attributes = [
                      { name: "data-width", value: "200px" },
                      { name: "data-allow-clear", value: "true" },
                      { name: "data-placeholder--id", value: null },
                      { name: "data-placeholder--value", value: "" },
                      { name: "data-search-url", value: url_for("display.search") },
                      { name: "data-search-term", value: "display" },
                      { name: "data-search-term-tags", value: "tags" },
                      { name: "data-id-property", value: "displayId" },
                      { name: "data-text-property", value: "display" }
                  ] %}
                  {{ inline.dropdown("displayId", "single", title, "", null, "displayId", "display", "", "pagedSelect", "", "", "", attributes) }}

                  {% set title %}{% trans "Partner" %}{% endset %}
                  {% set options = [{id: '', value: ''}] %}

                  {{ inline.dropdown("partnerId", "single", title, "", options, "id", "value") }}

                  <div class="w-100">
                      <a data-apply-button="true" class="btn btn-success">
                          <span>{% trans "Apply" %}</span>
                      </a>
                  </div>

                  <div class="alert alert-danger my-1">Please select a display</div>
              </form>
          </div>
      </div>
      <!-- Card Header -->
      <div class="card-header">
          <ul class="nav nav-tabs card-header-tabs" role="tablist">
              <li class="nav-item">
                  <a class="nav-link active" id="chart-tab" data-toggle="tab" href="#chartTab" role="tab"
                     aria-controls="chartTab" aria-selected="true">Summary</a>
              </li>
              <li class="nav-item">
                  <a class="nav-link" id="tabular-tab" data-toggle="tab" href="#tabularTab" role="tab"
                     aria-controls="tabularTab" aria-selected="false">Detailed</a>
              </li>
          </ul>
      </div>
      <!-- Card Body -->
      <div class="card-body">
          <div class="tab-content">

              <!-- SUMMARY TAB-->
              <div class="tab-pane active" id="chartTab" role="tabpanel" aria-labelledby="chart-tab">
                  <div class="XiboFilterCustom card bg-light pb-0 mb-0">
                      <div class="FilterDiv card-body" id="connector-ssp-activity-logs">
                          <form id="campaign-filter">
                              {% set title %}{% trans "Filter Options" %}{% endset %}
                              {% set options = [
                                  { optionid: "hour", option: "Hour" },
                                  { optionid: "errorCode", option: "Error Code" },
                                  { optionid: "hourerrorcode", option: "Hour and Error Code" },
                              ] %}
                              {{ inline.dropdown("campaignFilter", "single", title, "", options, "optionid", "option", helpText) }}
                              {{ forms.hidden("isDynamic", 1) }}
                          </form>

                          <!-- SUMMARY DATATABLE -->
                          <div class="XiboData card pt-3 my-3">
                              <table id="ssp-activity-summary"
                                     class="table table-striped table-full-width"
                                     style="width: 100%"
                                     data-state-preference-name="connector-ssp-activity-log-summary">
                                  <thead>
                                      <tr>
                                          <th>{% trans "Date" %}</th>
                                          <th>{% trans "Hour" %}</th>
                                          <th>{% trans "Campaign" %}</th>
                                          <th>{% trans "Play Count" %}</th>
                                          <th>{% trans "Error Count" %}</th>
                                          <th>{% trans "Misses Count" %}</th>
                                          <th>{% trans "Impressions" %}</th>
                                          <th>{% trans "Impression Actual" %}</th>
                                          <th>{% trans "Error Code" %}</th>
                                      </tr>
                                  </thead>
                                  <tbody>
                                  </tbody>
                                  <tfoot>
                                      <tr>
                                          <th></th>
                                          <th></th>
                                          <th></th>
                                          <th></th>
                                          <th></th>
                                          <th></th>
                                          <th></th>
                                          <th></th>
                                          <th></th>
                                      </tr>
                                  </tfoot>
                              </table>
                          </div>
                      </div>
                  </div>
                  <div class="widget mt-2 pb-2">
                      <div class="widget-title">
                          <i class="fa fa-tasks"></i>
                              {% trans "Summary Chart" %}
                          <div class="clearfix"></div>
                      </div>
                      <canvas id="canvas" style="clear:both; margin-top:25px;" height="100%"></canvas>
                  </div>
              </div>

              <!-- TABULAR TAB-->
              <div class="tab-pane show" id="tabularTab" role="tabpanel" aria-labelledby="tabular-tab">
                  <div class="XiboData card pt-3">
                      <table id="ssp-activity"
                             class="table table-striped table-full-width"
                             style="width: 100%"
                             data-state-preference-name="connector-ssp-activity-log" >
                          <thead>
                          <tr>
                              <th>{% trans "Scheduled At" %}</th>
                              <th>{% trans "Campaign" %}</th>
                              <th>{% trans "Display ID" %}</th>
                              <th>{% trans "Played?" %}</th>
                              <th>{% trans "Errored?" %}</th>
                              <th>{% trans "Impressions" %}</th>
                              <th>{% trans "Impression Date" %}</th>
                              <th>{% trans "Impression Actual" %}</th>
                              <th>{% trans "Errors" %}</th>
                              <th>{% trans "Error Date" %}</th>
                              <th>{% trans "Error Code" %}</th>
                          </tr>
                          </thead>
                          <tbody>
                          </tbody>
                          <tfoot>
                              <tr>
                                  <th></th>
                                  <th></th>
                                  <th></th>
                                  <th></th>
                                  <th></th>
                                  <th></th>
                                  <th></th>
                                  <th></th>
                                  <th></th>
                                  <th></th>
                                  <th></th>
                              </tr>
                          </tfoot>
                      </table>
                  </div>
              </div>
          </div>
      </div>
      <div class="card bg-light p-3 text-danger col-sm-12 text-center form-error"></div>
  </div>
</script>
