<?php

namespace app\AdminActions;

abstract class BaseAction
{
    protected int $recordId;
    protected ?int $adminId;
    protected int $timeStamp;
    protected int $ip;
    protected bool $isCli;

    protected static array $hashActionIds = [];

    public static function getActionId(): int {
        if (!array_key_exists(static::class, self::$hashActionIds)) {
            $class = static::class;
            if (($pos = strrpos($class, '\\')) !== false)
                $class = substr($class, $pos+1);
            $hash = hash('adler32', $class, true);
            self::$hashActionIds[static::class] = unpack('N', $hash)[1];
        }
        return self::$hashActionIds[static::class];
    }

    public function getActionName(): string {
        $cl = get_class($this);
        if (($pos = strrpos($cl, '\\')) !== false)
            $cl = substr($cl, $pos+1);
        return $cl;
    }

    public function setMetaInformation(int $record_id,
                                       ?int $admin_id,
                                       int $timestamp,
                                       int $ip,
                                       bool $is_cli) {
        $this->recordId = $record_id;
        $this->adminId = $admin_id;
        $this->timeStamp = $timestamp;
        $this->ip = $ip;
        $this->isCli = $is_cli;
    }

    public function getActorInfo(): array {
        return [$this->adminId, $this->isCli];
    }

    public function getAdminId(): ?int {
        return $this->adminId;
    }

    public function isCommandLineAction(): bool {
        return $this->isCli;
    }

    public function getDate(): string {
        return formatTime($this->timeStamp, ['short_months' => true]);
    }

    public function getTimeStamp(): int {
        return $this->timeStamp;
    }

    public function getIPv4(): string {
        return ulong2ip($this->ip);
    }

    public function getRecordId(): int {
        return $this->recordId;
    }

    public function renderHtml(): string {
        $rc = new \ReflectionClass($this);
        $lines = [];
        $fields = $rc->getProperties(\ReflectionProperty::IS_PUBLIC);
        foreach ($fields as $field) {
            $name = $field->getName();
            $rfield = new \ReflectionProperty(get_class($this), $name);
            if ($rfield->getType()->allowsNull() && is_null($this->{$name}))
                continue;
            if (is_array($this->{$name})) {
                $val = htmlescape(jsonEncode($this->{$name}));
            } else {
                $val = htmlescape($this->{$name});
            }
            $lines[] = $name.'='.$val;
        }
        return implode('<br>', $lines);
    }
}