<?php
namespace Misuzu\Forum;

use Index\DateTime;
use Index\Colour\Colour;
use Index\Data\IDbResult;

class ForumCategoryInfo {
    // should the types just be replaced with flags indicating what's allowed?
    public const TYPE_DISCUSSION = 0;
    public const TYPE_LISTING = 1;
    public const TYPE_LINK = 2;

    public const TYPE_ALIASES = [
        'discussion' => self::TYPE_DISCUSSION,
        'listing' => self::TYPE_LISTING,
        'link' => self::TYPE_LINK,
    ];

    public const MAY_HAVE_CHILDREN = [
        self::TYPE_DISCUSSION,
        self::TYPE_LISTING,
    ];

    public const MAY_HAVE_TOPICS = [
        self::TYPE_DISCUSSION,
    ];

    private string $id;
    private int $order;
    private ?string $parentId;
    private string $name;
    private int $type;
    private ?string $desc;
    private ?string $icon;
    private ?int $colour;
    private ?string $link;
    private ?int $clicks;
    private int $created;
    private bool $archived;
    private bool $hidden;
    private int $topicsCount;
    private int $postsCount;

    public function __construct(IDbResult $result) {
        $this->id = (string)$result->getInteger(0);
        $this->order = $result->getInteger(1);
        $this->parentId = $result->isNull(2) ? null : (string)$result->getInteger(2);
        $this->name = $result->getString(3);
        $this->type = $result->getInteger(4);
        $this->desc = $result->isNull(5) ? null : $result->getString(5);
        $this->icon = $result->isNull(6) ? null : $result->getString(6);
        $this->colour = $result->isNull(7) ? null : $result->getInteger(7);
        $this->link = $result->isNull(8) ? null : $result->getString(8);
        $this->clicks = $result->isNull(9) ? null : $result->getInteger(9);
        $this->created = $result->getInteger(10);
        $this->archived = $result->getInteger(11) !== 0;
        $this->hidden = $result->getInteger(12) !== 0;
        $this->topicsCount = $result->getInteger(13);
        $this->postsCount = $result->getInteger(14);
    }

    public function getId(): string {
        return $this->id;
    }

    public function getOrder(): int {
        return $this->order;
    }

    public function hasParent(): bool {
        return $this->parentId !== null && $this->parentId !== '0';
    }

    public function getParentId(): ?string {
        return $this->parentId;
    }

    public function isDirectChildOf(ForumCategoryInfo|string $parentInfo): bool {
        if($parentInfo instanceof ForumCategoryInfo)
            $parentInfo = $parentInfo->getId();
        return $this->hasParent() && $this->getParentId() === $parentInfo;
    }

    public function getName(): string {
        return $this->name;
    }

    public function getType(): int {
        return $this->type;
    }

    public function isDiscussion(): bool {
        return $this->type === self::TYPE_DISCUSSION;
    }

    public function isListing(): bool {
        return $this->type === self::TYPE_LISTING;
    }

    public function isLink(): bool {
        return $this->type === self::TYPE_LINK;
    }

    public function mayHaveChildren(): bool {
        return in_array($this->type, self::MAY_HAVE_CHILDREN);
    }

    public function mayHaveTopics(): bool {
        return in_array($this->type, self::MAY_HAVE_TOPICS);
    }

    public function hasDescription(): bool {
        return $this->desc !== null && $this->desc !== '';
    }

    public function getDescription(): ?string {
        return $this->desc;
    }

    public function hasIcon(): bool {
        return $this->icon !== null && $this->icon !== '';
    }

    public function getIcon(): ?string {
        return $this->icon;
    }

    public function getIconForDisplay(): string {
        if($this->hasIcon())
            return $this->getIcon();

        if($this->isArchived())
            return 'fas fa-archive fa-fw';

        return match($this->type) {
            self::TYPE_LISTING => 'fas fa-folder fa-fw',
            self::TYPE_LINK => 'fas fa-link fa-fw',
            default => 'fas fa-comments fa-fw',
        };
    }

    public function hasColour(): bool {
        return $this->colour !== null && ($this->colour & 0x40000000) === 0;
    }

    public function getColourRaw(): ?int {
        return $this->colour;
    }

    public function getColour(): Colour {
        return $this->colour === null ? Colour::none() : Colour::fromMisuzu($this->colour);
    }

    public function hasLinkTarget(): bool {
        return $this->link !== null && $this->link !== '';
    }

    public function getLinkTarget(): ?string {
        return $this->link;
    }

    public function hasLinkClicks(): bool {
        return $this->clicks !== null;
    }

    public function getLinkClicks(): ?int {
        return $this->clicks;
    }

    public function getCreatedTime(): int {
        return $this->created;
    }

    public function getCreatedAt(): DateTime {
        return DateTime::fromUnixTimeSeconds($this->created);
    }

    public function isArchived(): bool {
        return $this->archived;
    }

    public function isHidden(): bool {
        return $this->hidden;
    }

    public function getTopicsCount(): int {
        return $this->topicsCount;
    }

    public function getPostsCount(): int {
        return $this->postsCount;
    }
}
