<?php
/**
 * Copyright 2020 Adobe
 * All Rights Reserved.
 *
 * NOTICE: Adobe permits you to use, modify, and distribute this file in
 * accordance with the terms of the Adobe license agreement accompanying
 * it.
 */
declare(strict_types=1);

namespace Sut\Domain\Statistics;

use DateInterval;
use DateTime;

/**
 * Class Statistics holds metadata related to a SUT run, such as its running time and number of modules scanned.
 */
class Statistics
{
    /**
     * @var DateTime
     */
    private $startTime;

    /**
     * @var DateTime
     */
    private $endTime;

    /**
     * @var int
     */
    private $processedModules = 0;

    /**
     * @var int[]
     */
    private $numberOfWarnings = [];

    /**
     * @var int[]
     */
    private $numberOfErrors = [];

    /**
     * @var int[]
     */
    private $numberOfCriticals = [];

    /**
     * @var string
     */
    private $magentoCurrentVersion = '';

    /**
     * @var string
     */
    private $magentoComingVersion = '';

    /**
     * @var string
     */
    private $magentoCurrentEdition;

    /**
     * @var int
     */
    private $totalCoreCheckedFiles;

    /**
     * @var int
     */
    private $totalCoreModifiedFiles;

    /**
     * @var float
     */
    private $memoryPeakUsage;

    /**
     * This array is intended to contain information that do not fall in any of the other fields.
     * @var array
     */
    private $custom = [];

    /**
     * Statistics constructor.
     */
    public function __construct()
    {
        $this->startTime = new DateTime();
        $this->endTime = new DateTime();
    }

    /**
     * @param DateTime $startTime
     * @return Statistics
     */
    public function setStartTime(DateTime $startTime): Statistics
    {
        $this->startTime = $startTime;
        return $this;
    }

    /**
     * @param DateTime $endTime
     * @return Statistics
     */
    public function setEndTime(DateTime $endTime): Statistics
    {
        $this->endTime = $endTime;
        return $this;
    }

    /**
     * Increment processed modules counter
     */
    public function incrementProcessedModules(): void
    {
        $this->processedModules++;
    }

    /**
     * @param int $numberOfModules
     */
    public function setProcessedModules(int $numberOfModules): void
    {
        $this->processedModules = $numberOfModules;
    }

    /**
     * @return int
     */
    public function getProcessedModules(): int
    {
        return $this->processedModules;
    }

    /**
     * @return DateInterval
     */
    public function getTotalTime(): DateInterval
    {
        return $this->endTime->diff($this->startTime);
    }

    /**
     * @param string $origin
     * @return int|null
     */
    public function getNumberOfWarnings(string $origin): ?int
    {
        return $this->numberOfWarnings[$origin] ?? null;
    }

    /**
     * @param string $origin
     * @param int $numberOfWarnings
     */
    public function setNumberOfWarnings(string $origin, int $numberOfWarnings): void
    {
        $this->numberOfWarnings[$origin] = $numberOfWarnings;
    }

    /**
     * @param string $origin
     * @return int|null
     */
    public function getNumberOfErrors(string $origin): ?int
    {
        return $this->numberOfErrors[$origin] ?? null;
    }

    /**
     * @param string $origin
     * @param int $numberOfErrors
     */
    public function setNumberOfErrors(string $origin, int $numberOfErrors): void
    {
        $this->numberOfErrors[$origin] = $numberOfErrors;
    }

    /**
     * @param string $origin
     * @return int|null
     */
    public function getNumberOfCriticals(string $origin): ?int
    {
        return $this->numberOfCriticals[$origin] ?? null;
    }

    /**
     * @param string $origin
     * @param int $numberOfCriticals
     */
    public function setNumberOfCriticals(string $origin, int $numberOfCriticals): void
    {
        $this->numberOfCriticals[$origin] = $numberOfCriticals;
    }

    /**
     * @return string
     */
    public function getMagentoCurrentVersion(): string
    {
        return $this->magentoCurrentVersion;
    }

    /**
     * @param string $magentoCurrentVersion
     */
    public function setMagentoCurrentVersion(string $magentoCurrentVersion): void
    {
        $this->magentoCurrentVersion = $magentoCurrentVersion;
    }

    /**
     * @return string
     */
    public function getMagentoComingVersion(): string
    {
        return $this->magentoComingVersion;
    }

    /**
     * @param string $magentoComingVersion
     */
    public function setMagentoComingVersion(string $magentoComingVersion): void
    {
        $this->magentoComingVersion = $magentoComingVersion;
    }

    /**
     * @return float
     */
    public function getMemoryPeakUsage(): float
    {
        return $this->memoryPeakUsage;
    }

    /**
     * @param float $memoryPeakUsage
     */
    public function setMemoryPeakUsage(float $memoryPeakUsage): void
    {
        $this->memoryPeakUsage = $memoryPeakUsage;
    }

    /**
     * @param array $custom
     */
    public function setCustom(array $custom): void
    {
        $this->custom = $custom;
    }

    /**
     * @return array
     */
    public function getCustom(): array
    {
        return $this->custom;
    }

    /**
     * @param int $totalCoreCheckedFiles
     */
    public function setTotalCoreCheckedFiles(int $totalCoreCheckedFiles): void
    {
        $this->totalCoreCheckedFiles = $totalCoreCheckedFiles;
    }

    /**
     * @param int $totalCoreModifiedFiles
     */
    public function setTotalCoreModifiedFiles(int $totalCoreModifiedFiles): void
    {
        $this->totalCoreModifiedFiles = $totalCoreModifiedFiles;
    }

    /**
     * @return int|null
     */
    public function getTotalCoreModifiedFiles(): ?int
    {
        return $this->totalCoreModifiedFiles;
    }

    /**
     * @return int|null
     */
    public function getTotalCoreCheckedFiles(): ?int
    {
        return $this->totalCoreCheckedFiles;
    }

    /**
     * @return float|null
     */
    public function getPercentageOfCoreModifiedFiles(): ?float
    {
        if (!$this->totalCoreCheckedFiles || !$this->totalCoreModifiedFiles) {
            return null;
        }

        if ($this->totalCoreCheckedFiles > 0) {
            return $this->totalCoreModifiedFiles / $this->totalCoreCheckedFiles * 100;
        }
        return 0.0;
    }

    /**
     * @param string $currentEdition
     */
    public function setMagentoCurrentEdition(string $currentEdition): void
    {
        $this->magentoCurrentEdition = $currentEdition;
    }

    /**
     * @return string
     */
    public function getMagentoCurrentEdition(): string
    {
        return $this->magentoCurrentEdition;
    }
}
