<?php declare(strict_types=1);
namespace Newland\Toubiz\Sync\Neos\Domain\Model;

/*
 * This file is part of the "toubiz-sync-neos" package.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 */

/**
 * A collection of weather data.
 *
 * This holds dated weather data for one day.
 */
class Weather
{
    /** @var array */
    protected $data = [];

    public function __construct(array $data = [])
    {
        $this->setData($data);
    }

    /**
     * @param array $data
     * @return void
     */
    public function setData(array $data): void
    {
        $this->data = $data;
    }

    /**
     * Returns the main date for the data group.
     *
     * @return string|int
     */
    public function getDate()
    {
        return array_keys($this->data)[0] ?? '';
    }

    /**
     * Returns the symbol code for the data group.
     *
     * @return int|string
     */
    public function getSymbol()
    {
        $count = [];
        foreach ($this->data as $date => $entry) {
            $hour = (int) (new \DateTime($date))->format('H');
            if ($hour >= 8 && $hour <= 18) {
                if (!array_key_exists($entry['symbol'], $count)) {
                    $count[$entry['symbol']] = 1;
                } else {
                    $count[$entry['symbol']]++;
                }
            }
        }
        return array_keys($count, max($count))[0];
    }

    /**
     * Returns key time entries.
     *
     * Meteotest returns bigger arrays every 6 hours.
     *
     * @return array
     */
    public function getKeyTimes(): array
    {
        $data = [];
        foreach ($this->data as $key => $entry) {
            if (count($entry) >= 11) {
                $data[$key] = $entry;
            }
        }
        return $data;
    }

    /**
     * Gets minimum temperature from dataset.
     *
     * @return float
     */
    public function getMinimumTemperature(): float
    {
        $temperatures = [];
        foreach ($this->getKeyTimes() as $entry) {
            $temperatures[] = $entry['minimumTemperature'];
        }
        return min($temperatures);
    }

    /**
     * Gets maximum temperature from dataset.
     *
     * @return float
     */
    public function getMaximumTemperature(): float
    {
        $temperatures = [];
        foreach ($this->getKeyTimes() as $entry) {
            $temperatures[] = $entry['maximumTemperature'];
        }
        return max($temperatures);
    }

    /**
     * Returns the daily sunshine duration.
     *
     * @return int Minutes
     */
    public function getSunshineDuration(): int
    {
        $duration = 0;
        foreach ($this->data as $entry) {
            $duration += (int) $entry['sunshineDuration'];
        }
        return $duration;
    }

    /**
     * Returns the key time that is next to the current time.
     *
     * @return array|null
     */
    public function getCurrentKeyTime(): ?array
    {
        $currentHour = (int) (new \DateTime)->format('H');
        foreach ($this->getKeyTimes() as $key => $entry) {
            $hour = (int) (new \DateTime($key))->format('H');
            $diff = $hour - $currentHour;
            if ($diff > 0 && $diff < 3) {
                return [
                    $key => $entry,
                ];
            }
        }

        return null;
    }

    /**
     * Returns main time entries.
     *
     * Main times are defined as 3 hour intervals
     * from 6am to 9pm.
     *
     * @return array
     */
    public function getMainTimes(): array
    {
        $data = [];
        foreach ($this->data as $key => $entry) {
            $hour = (int) (new \DateTime($key))->format('H');
            if ($hour >= 6 && $hour <= 21 && $hour % 3 === 0) {
                $data[$key] = $entry;
            }
        }
        return $data;
    }
}
