<?php

// SPDX-FileCopyrightText: 2024 Icinga GmbH <https://icinga.com>
// SPDX-License-Identifier: GPL-3.0-or-later

namespace Icinga\Module\Notifications\Widget\Timeline;

use DateTimeZone;
use Icinga\Module\Notifications\Widget\TimeGrid;
use Icinga\Module\Notifications\Widget\TimeGrid\BaseGrid;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\HtmlElement;
use ipl\Html\Text;
use ipl\Web\Widget\Icon;

class Entry extends TimeGrid\Entry
{
    protected ?Member $member = null;

    /** @var ?EntryFlyout Content of the flyoutmenu that is shown when the entry is hovered */
    protected ?EntryFlyout $flyoutContent = null;

    /** @var ?DateTimeZone The timezone the schedule is created in */
    protected ?DateTimeZone $scheduleTimezone = null;

    /**
     * @var string A CSS class that changes the placement of the flyout
     *
     * "narrow-entry": centers the flyout's caret on the entry
     * "medium-entry": behaves like narrow entry in minimal and poor layout, otherwise as a wide entry
     * "wide-entry": the flyout has a fixed offset
     */
    protected string $widthClass = "wide-entry";

    public function setMember(Member $member): static
    {
        $this->member = $member;

        return $this;
    }

    public function getMember(): ?Member
    {
        return $this->member;
    }

    public function getColor(int $transparency): string
    {
        return TimeGrid\Util::calculateEntryColor($this->getMember()->getName(), $transparency);
    }

    /**
     * Set content of a tooltip that is shown when the entry is hovered
     *
     * @param EntryFlyout $content
     *
     * @return static
     */
    public function setFlyoutContent(EntryFlyout $content): static
    {
        $this->flyoutContent = $content;

        return $this;
    }

    /**
     * Return the entry's flyout element
     *
     * @return EntryFlyout|null
     */
    public function getFlyoutContent(): ?EntryFlyout
    {
        return $this->flyoutContent;
    }

    /**
     * Set the timezone the schedule is created in
     *
     * @param DateTimeZone $scheduleTimezone
     *
     * @return $this
     */
    public function setScheduleTimezone(DateTimeZone $scheduleTimezone): static
    {
        $this->scheduleTimezone = $scheduleTimezone;

        return $this;
    }

    /**
     * Get the timezone the schedule is created in
     *
     * @return DateTimeZone|null
     */
    public function getScheduleTimezone(): ?DateTimeZone
    {
        return $this->scheduleTimezone;
    }

    /**
     * Set value of $widthClass which will be a CSS class of the rendered entry
     *
     * @param string $widthClass
     *
     * @return $this
     */
    public function setWidthClass(string $widthClass): static
    {
        $this->widthClass = $widthClass;

        return $this;
    }

    /**
     * Return the current width class
     *
     * @return string
     */
    public function getWidthClass(): string
    {
        return $this->widthClass;
    }

    /**
     * Assign a width class based on the fraction of the grid duration occupied by this entry
     *
     * @param BaseGrid $grid
     * @param float $mediumThreshold Fraction of grid duration below which the entry is considered medium width
     * @param float $narrowThreshold Fraction of grid duration below which the entry is considered narrow
     *
     * @return $this
     */
    public function calculateAndSetWidthClass(
        BaseGrid $grid,
        float $mediumThreshold = 0.2,
        float $narrowThreshold = 0.1
    ): static {
        $totalGridDuration = $grid->getGridEnd()->getTimestamp() - $grid->getGridStart()->getTimestamp();
        $start = max($this->getStart()->getTimestamp(), $grid->getGridStart()->getTimestamp());
        $end = min($this->getEnd()->getTimestamp(), $grid->getGridEnd()->getTimestamp());
        $duration = $end - $start;
        if ($duration / $totalGridDuration < $narrowThreshold) {
            $this->setWidthClass('narrow-entry');
        } elseif ($duration / $totalGridDuration < $mediumThreshold) {
            $this->setWidthClass('medium-entry');
        } else {
            $this->setWidthClass('wide-entry');
        }

        return $this;
    }

    protected function assembleContainer(BaseHtmlElement $container): void
    {
        $container->addHtml(
            new HtmlElement(
                'div',
                Attributes::create(['class' => 'title']),
                new Icon($this->getMember()->getIcon()),
                new HtmlElement(
                    'span',
                    Attributes::create(['class' => 'name']),
                    Text::create($this->getMember()->getName())
                )
            )
        );

        if (isset($this->flyoutContent)) {
            $this->addHtml($this->flyoutContent->forEntry($this));
            $this->getAttributes()->add('class', $this->getWidthClass());
        }
    }
}
