<?php
namespace Misuzu\Users;

use Index\DateTime;
use Index\TimeZoneInfo;
use Index\Colour\Colour;
use Index\Data\IDbResult;
use Index\Net\IPAddress;
use Misuzu\Parsers\Parser;

class UserInfo {
    private string $id;
    private string $name;
    private ?string $passwordHash;
    private string $emailAddr;
    private string $registerRemoteAddr;
    private string $lastRemoteAddr;
    private bool $super;
    private string $countryCode;
    private ?int $colour;
    private int $created;
    private ?int $lastActive;
    private ?int $deleted;
    private ?string $displayRoleId;
    private ?string $totpKey;
    private ?string $aboutContent;
    private int $aboutParser;
    private ?string $signatureContent;
    private int $signatureParser;
    private ?string $birthdate;
    private ?int $backgroundSettings;
    private ?string $title;

    public function __construct(IDbResult $result) {
        $this->id = (string)$result->getInteger(0);
        $this->name = $result->getString(1);
        $this->passwordHash = $result->isNull(2) ? null : $result->getString(2);
        $this->emailAddr = $result->getString(3);
        $this->registerRemoteAddr = $result->getString(4);
        $this->lastRemoteAddr = $result->isNull(5) ? null : $result->getString(5);
        $this->super = $result->getInteger(6) !== 0;
        $this->countryCode = $result->getString(7);
        $this->colour = $result->isNull(8) ? null : $result->getInteger(8);
        $this->created = $result->getInteger(9);
        $this->lastActive = $result->isNull(10) ? null : $result->getInteger(10);
        $this->deleted = $result->isNull(11) ? null : $result->getInteger(11);
        $this->displayRoleId = $result->isNull(12) ? null : (string)$result->getInteger(12);
        $this->totpKey = $result->isNull(13) ? null : $result->getString(13);
        $this->aboutContent = $result->isNull(14) ? null : $result->getString(14);
        $this->aboutParser = $result->getInteger(15);
        $this->signatureContent = $result->isNull(16) ? null : $result->getString(16);
        $this->signatureParser = $result->getInteger(17);
        $this->birthdate = $result->isNull(18) ? null : $result->getString(18);
        $this->backgroundSettings = $result->isNull(19) ? null : $result->getInteger(19);
        $this->title = $result->getString(20);
    }

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

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

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

    public function getPasswordHash(): ?string {
        return $this->passwordHash;
    }

    public function passwordNeedsRehash(): bool {
        return $this->hasPasswordHash() && Users::passwordNeedsRehash($this->passwordHash);
    }

    public function verifyPassword(string $password): bool {
        return $this->hasPasswordHash() && password_verify($password, $this->passwordHash);
    }

    public function getEMailAddress(): string {
        return $this->emailAddr;
    }

    public function getRegisterRemoteAddressRaw(): string {
        return $this->registerRemoteAddr;
    }

    public function getRegisterRemoteAddress(): IPAddress {
        return IPAddress::parse($this->registerRemoteAddr);
    }

    public function getLastRemoteAddressRaw(): string {
        return $this->lastRemoteAddr;
    }

    public function getLastRemoteAddress(): IPAddress {
        return IPAddress::parse($this->lastRemoteAddr);
    }

    public function isSuperUser(): bool {
        return $this->super;
    }

    public function hasCountryCode(): bool {
        return $this->countryCode !== 'XX';
    }

    public function getCountryCode(): string {
        return $this->countryCode;
    }

    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 getCreatedTime(): int {
        return $this->created;
    }

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

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

    public function getLastActiveTime(): ?int {
        return $this->lastActive;
    }

    public function getLastActiveAt(): ?DateTime {
        return $this->lastActive === null ? null : DateTime::fromUnixTimeSeconds($this->lastActive);
    }

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

    public function getDeletedTime(): ?int {
        return $this->deleted;
    }

    public function getDeletedAt(): ?DateTime {
        return $this->deleted === null ? null : DateTime::fromUnixTimeSeconds($this->deleted);
    }

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

    public function getDisplayRoleId(): ?string {
        return $this->displayRoleId;
    }

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

    public function getTOTPKey(): ?string {
        return $this->totpKey;
    }

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

    public function getAboutContent(): ?string {
        return $this->aboutContent;
    }

    public function getAboutParser(): int {
        return $this->aboutParser;
    }

    public function isAboutBodyPlain(): bool {
        return $this->aboutParser === Parser::PLAIN;
    }

    public function isAboutBodyBBCode(): bool {
        return $this->aboutParser === Parser::BBCODE;
    }

    public function isAboutBodyMarkdown(): bool {
        return $this->aboutParser === Parser::MARKDOWN;
    }

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

    public function getSignatureContent(): ?string {
        return $this->signatureContent;
    }

    public function getSignatureParser(): int {
        return $this->signatureParser;
    }

    public function isSignatureBodyPlain(): bool {
        return $this->signatureParser === Parser::PLAIN;
    }

    public function isSignatureBodyBBCode(): bool {
        return $this->signatureParser === Parser::BBCODE;
    }

    public function isSignatureBodyMarkdown(): bool {
        return $this->signatureParser === Parser::MARKDOWN;
    }

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

    public function getBirthdateRaw(): ?string {
        return $this->birthdate;
    }

    public function getBirthdate(): ?DateTime {
        return $this->birthdate === null ? null : DateTime::createFromFormat('Y-m-d', $this->birthdate, TimeZoneInfo::utc());
    }

    public function getAge(): int {
        $birthdate = $this->getBirthdate();
        if($birthdate === null || $birthdate->getYear() < 1900)
            return -1;
        return (int)$birthdate->diff(DateTime::now())->format('%y');
    }

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

    public function getBackgroundSettings(): ?int {
        return $this->backgroundSettings;
    }

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

    public function getTitle(): ?string {
        return $this->title;
    }
}
