<?php

/**
 * Matomo - free/libre analytics platform
 *
 * @link    https://matomo.org
 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
 */
namespace Piwik\Plugins\PagePerformance\RecordBuilders;

use Piwik\ArchiveProcessor;
use Piwik\ArchiveProcessor\Record;
use Piwik\ArchiveProcessor\RecordBuilder;
use Piwik\Plugins\PagePerformance\Archiver;
use Piwik\Plugins\PagePerformance\Columns\Base;
use Piwik\Plugins\PagePerformance\Columns\TimeDomCompletion;
use Piwik\Plugins\PagePerformance\Columns\TimeDomProcessing;
use Piwik\Plugins\PagePerformance\Columns\TimeNetwork;
use Piwik\Plugins\PagePerformance\Columns\TimeOnLoad;
use Piwik\Plugins\PagePerformance\Columns\TimeServer;
use Piwik\Plugins\PagePerformance\Columns\TimeTransfer;
class PerformanceTotals extends RecordBuilder
{
    public function getRecordMetadata(ArchiveProcessor $archiveProcessor) : array
    {
        return [Record::make(Record::TYPE_NUMERIC, Archiver::PAGEPERFORMANCE_TOTAL_NETWORK_TIME), Record::make(Record::TYPE_NUMERIC, Archiver::PAGEPERFORMANCE_TOTAL_NETWORK_HITS), Record::make(Record::TYPE_NUMERIC, Archiver::PAGEPERFORMANCE_TOTAL_SERVER_TIME), Record::make(Record::TYPE_NUMERIC, Archiver::PAGEPERFORMANCE_TOTAL_SERVER_HITS), Record::make(Record::TYPE_NUMERIC, Archiver::PAGEPERFORMANCE_TOTAL_TRANSFER_TIME), Record::make(Record::TYPE_NUMERIC, Archiver::PAGEPERFORMANCE_TOTAL_TRANSFER_HITS), Record::make(Record::TYPE_NUMERIC, Archiver::PAGEPERFORMANCE_TOTAL_DOMPROCESSING_TIME), Record::make(Record::TYPE_NUMERIC, Archiver::PAGEPERFORMANCE_TOTAL_DOMPROCESSING_HITS), Record::make(Record::TYPE_NUMERIC, Archiver::PAGEPERFORMANCE_TOTAL_DOMCOMPLETION_TIME), Record::make(Record::TYPE_NUMERIC, Archiver::PAGEPERFORMANCE_TOTAL_DOMCOMPLETION_HITS), Record::make(Record::TYPE_NUMERIC, Archiver::PAGEPERFORMANCE_TOTAL_ONLOAD_TIME), Record::make(Record::TYPE_NUMERIC, Archiver::PAGEPERFORMANCE_TOTAL_ONLOAD_HITS), Record::make(Record::TYPE_NUMERIC, Archiver::PAGEPERFORMANCE_TOTAL_PAGE_LOAD_TIME), Record::make(Record::TYPE_NUMERIC, Archiver::PAGEPERFORMANCE_TOTAL_PAGE_LOAD_HITS)];
    }
    protected function aggregate(ArchiveProcessor $archiveProcessor) : array
    {
        $logAggregator = $archiveProcessor->getLogAggregator();
        $totals = [];
        $selects = $totalColumns = $allColumns = [];
        $table = 'log_link_visit_action';
        /**
         * @var Base[] $performanceDimensions
         */
        $performanceDimensions = [new TimeNetwork(), new TimeServer(), new TimeTransfer(), new TimeDomProcessing(), new TimeDomCompletion(), new TimeOnLoad()];
        foreach ($performanceDimensions as $dimension) {
            $column = $dimension->getColumnName();
            $selects[] = "sum(" . sprintf($dimension->getSqlCappedValue(), $table . '.' . $column) . ") as {$column}_total";
            $selects[] = "sum(if({$table}.{$column} is null, 0, 1)) as {$column}_hits";
            $totalColumns[] = sprintf($dimension->getSqlCappedValue(), $table . '.' . $column);
            $allColumns[] = "{$table}.{$column}";
        }
        $selects[] = sprintf('SUM(%s) as page_load_total', implode(' + ', $totalColumns));
        $selects[] = "count({$table}.idlink_va) as page_load_hits";
        $joinLogActionOnColumn = array('idaction_url');
        $where = sprintf("COALESCE(%s) IS NOT NULL", implode(',', $allColumns));
        $query = $logAggregator->queryActionsByDimension([], $where, $selects, \false, null, $joinLogActionOnColumn, null, -1);
        $result = $query->fetchAll();
        $totals[Archiver::PAGEPERFORMANCE_TOTAL_NETWORK_TIME] = $this->sumMetric($result, 'time_network_total');
        $totals[Archiver::PAGEPERFORMANCE_TOTAL_NETWORK_HITS] = $this->sumMetric($result, 'time_network_hits');
        $totals[Archiver::PAGEPERFORMANCE_TOTAL_SERVER_TIME] = $this->sumMetric($result, 'time_server_total');
        $totals[Archiver::PAGEPERFORMANCE_TOTAL_SERVER_HITS] = $this->sumMetric($result, 'time_server_hits');
        $totals[Archiver::PAGEPERFORMANCE_TOTAL_TRANSFER_TIME] = $this->sumMetric($result, 'time_transfer_total');
        $totals[Archiver::PAGEPERFORMANCE_TOTAL_TRANSFER_HITS] = $this->sumMetric($result, 'time_transfer_hits');
        $totals[Archiver::PAGEPERFORMANCE_TOTAL_DOMPROCESSING_TIME] = $this->sumMetric($result, 'time_dom_processing_total');
        $totals[Archiver::PAGEPERFORMANCE_TOTAL_DOMPROCESSING_HITS] = $this->sumMetric($result, 'time_dom_processing_hits');
        $totals[Archiver::PAGEPERFORMANCE_TOTAL_DOMCOMPLETION_TIME] = $this->sumMetric($result, 'time_dom_completion_total');
        $totals[Archiver::PAGEPERFORMANCE_TOTAL_DOMCOMPLETION_HITS] = $this->sumMetric($result, 'time_dom_completion_hits');
        $totals[Archiver::PAGEPERFORMANCE_TOTAL_ONLOAD_TIME] = $this->sumMetric($result, 'time_on_load_total');
        $totals[Archiver::PAGEPERFORMANCE_TOTAL_ONLOAD_HITS] = $this->sumMetric($result, 'time_on_load_hits');
        $totals[Archiver::PAGEPERFORMANCE_TOTAL_PAGE_LOAD_TIME] = $this->sumMetric($result, 'page_load_total');
        $totals[Archiver::PAGEPERFORMANCE_TOTAL_PAGE_LOAD_HITS] = $this->sumMetric($result, 'page_load_hits');
        return $totals;
    }
    private function sumMetric(array $result, string $field) : int
    {
        $total = 0;
        foreach ($result as $row) {
            if (!empty($row[$field])) {
                $total += (int) $row[$field];
            }
        }
        return $total;
    }
}
