<?php
namespace Misuzu\AuditLog;

use ValueError;
use Index\DateTime;
use Index\Data\IDbResult;
use Index\Net\IPAddress;

class AuditLogInfo {
    private ?string $userId;
    private string $action;
    private array $params;
    private int $created;
    private string $address;
    private string $country;

    public function __construct(IDbResult $result) {
        $this->userId = $result->isNull(0) ? null : (string)$result->getInteger(0);
        $this->action = $result->getString(1);
        $this->params = json_decode($result->getString(2));
        $this->created = $result->getInteger(3);
        $this->address = $result->isNull(4) ? '::1' : $result->getString(4); // apparently this being NULL is possible?
        $this->country = $result->getString(5);
    }

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

    public function getUserId(): ?string {
        return $this->userId;
    }

    public function getAction(): string {
        return $this->action;
    }

    public function getParams(): array {
        return $this->params;
    }

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

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

    public function getRemoteAddressRaw(): string {
        return $this->address;
    }

    public function getRemoteAddress(): IPAddress {
        return IPAddress::parse($this->address);
    }

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

    public function getFormatted(): string {
        if(array_key_exists($this->action, self::FORMATS))
            try {
                return vsprintf(self::FORMATS[$this->action], $this->params);
            } catch(ValueError $ex) {}

        return sprintf('%s(%s)', $this->action, implode(', ', $this->params));
    }

    public const FORMATS = [
        'PERSONAL_EMAIL_CHANGE'        => 'Changed e-mail address to %s.',
        'PERSONAL_PASSWORD_CHANGE'     => 'Changed account password.',
        'PERSONAL_SESSION_DESTROY'     => 'Ended session #%d.',
        'PERSONAL_SESSION_DESTROY_ALL' => 'Ended all personal sessions.',
        'PERSONAL_DATA_DOWNLOAD'       => 'Downloaded archive of account data.',

        'PASSWORD_RESET' => 'Successfully used the password reset form to change password.',

        'CHANGELOG_ENTRY_CREATE'  => 'Created a new changelog entry #%d.',
        'CHANGELOG_ENTRY_EDIT'    => 'Edited changelog entry #%d.',
        'CHANGELOG_TAG_ADD'       => 'Added tag #%2$d to changelog entry #%1$d.',
        'CHANGELOG_TAG_REMOVE'    => 'Removed tag #%2$d from changelog entry #%1$d.',
        'CHANGELOG_TAG_CREATE'    => 'Created new changelog tag #%d.',
        'CHANGELOG_TAG_EDIT'      => 'Edited changelog tag #%d.',
        'CHANGELOG_TAG_DELETE'    => 'Deleted changelog tag #%d.',
        'CHANGELOG_ACTION_CREATE' => 'Created new changelog action #%d.',
        'CHANGELOG_ACTION_EDIT'   => 'Edited changelog action #%d.',

        'COMMENT_ENTRY_DELETE'     => 'Deleted comment #%d.',
        'COMMENT_ENTRY_DELETE_MOD' => 'Deleted comment #%d by user #%d %s.',
        'COMMENT_ENTRY_RESTORE'    => 'Restored comment #%d by user #%d %s.',

        'NEWS_POST_CREATE'     => 'Created news post #%d.',
        'NEWS_POST_EDIT'       => 'Edited news post #%d.',
        'NEWS_POST_DELETE'     => 'Deleted news post #%d.',
        'NEWS_CATEGORY_CREATE' => 'Created news category #%d.',
        'NEWS_CATEGORY_EDIT'   => 'Edited news category #%d.',
        'NEWS_CATEGORY_DELETE' => 'Deleted news category #%d.',

        'FORUM_POST_EDIT'    => 'Edited forum post #%d.',
        'FORUM_POST_DELETE'  => 'Deleted forum post #%d.',
        'FORUM_POST_RESTORE' => 'Restored forum post #%d.',
        'FORUM_POST_NUKE'    => 'Nuked forum post #%d.',

        'FORUM_TOPIC_DELETE'       => 'Deleted forum topic #%d.',
        'FORUM_TOPIC_RESTORE'      => 'Restored forum topic #%d.',
        'FORUM_TOPIC_NUKE'         => 'Nuked forum topic #%d.',
        'FORUM_TOPIC_BUMP'         => 'Manually bumped forum topic #%d.',
        'FORUM_TOPIC_LOCK'         => 'Locked forum topic #%d.',
        'FORUM_TOPIC_UNLOCK'       => 'Unlocked forum topic #%d.',
        'FORUM_TOPIC_REDIR_CREATE' => 'Created redirect for topic #%d.',
        'FORUM_TOPIC_REDIR_REMOVE' => 'Removed redirect for topic #%d.',

        'CONFIG_CREATE' => 'Created config value with name "%s".',
        'CONFIG_UPDATE' => 'Updated config value with name "%s".',
        'CONFIG_DELETE' => 'Deleted config value with name "%s".',

        'EMOTICON_CREATE' => 'Created emoticon #%s.',
        'EMOTICON_EDIT'   => 'Edited emoticon #%s.',
        'EMOTICON_DELETE' => 'Deleted emoticon #%s.',
        'EMOTICON_ORDER'  => 'Changed order of emoticon #%s.',
        'EMOTICON_ALIAS'  => 'Added alias "%2$s" to emoticon #%1$s.',

        'MOD_NOTE_CREATE' => 'Added moderator note #%d to user #%d.',
        'MOD_NOTE_UPDATE' => 'Edited moderator note #%d on user #%d.',
        'MOD_NOTE_DELETE' => 'Removed moderator note #%d from user #%d.',

        'BAN_CREATE' => 'Added ban #%d to user #%d.',
        'BAN_DELETE' => 'Removed ban #%d from user #%d.',

        'WARN_CREATE' => 'Added warning #%d to user #%d.',
        'WARN_DELETE' => 'Removed warning #%d from user #%d.',

        'ROLE_CREATE' => 'Created role #%d.',
        'ROLE_UPDATE' => 'Updated role #%d.',

        'USER_IMPERSONATE' => 'Impersonated user #%d %s.',
    ];
}
