<?php

namespace engine\logging;

class FileLogger extends Logger
{
    public function __construct(protected string $logFile) {}

    protected function writer(LogLevel $level,
                              int      $num,
                              string   $message,
                              ?int     $errno = null,
                              ?string  $errfile = null,
                              ?string  $errline = null,
                              ?string  $stacktrace = null): void {
        if (is_null($this->logFile)) {
            fprintf(STDERR, __METHOD__.': logfile is not set');
            return;
        }

        $time = time();

        // TODO rewrite using sprintf
        $exec_time = strval(exectime());
        if (strlen($exec_time) < 6)
            $exec_time .= str_repeat('0', 6 - strlen($exec_time));

        $title = isCli() ? 'cli' : $_SERVER['REQUEST_URI'];
        $date = date('d/m/y H:i:s', $time);

        $buf = '';
        if ($num == 0) {
            $buf .= Util::ansi(" $title ",
                fg: AnsiColor::WHITE,
                bg: AnsiColor::MAGENTA,
                bold: true,
                fg_bright: true);
            $buf .= Util::ansi(" $date ", fg: AnsiColor::WHITE, bg: AnsiColor::BLUE, fg_bright: true);
            $buf .= "\n";
        }

        $letter = strtoupper($level->name[0]);
        $color = match ($level) {
            LogLevel::ERROR => AnsiColor::RED,
            // LogLevel::INFO => AnsiColor::GREEN,
            LogLevel::DEBUG => AnsiColor::WHITE,
            LogLevel::WARNING => AnsiColor::YELLOW
        };

        $buf .= Util::ansi($letter.Util::ansi('='.Util::ansi($num, bold: true)), fg: $color).' ';
        $buf .= Util::ansi($exec_time, fg: AnsiColor::CYAN).' ';
        if (!is_null($errno)) {
            $buf .= Util::ansi($errfile, fg: AnsiColor::GREEN);
            $buf .= Util::ansi(':', fg: AnsiColor::WHITE);
            $buf .= Util::ansi($errline, fg: AnsiColor::GREEN, fg_bright: true);
            $buf .= ' ('.Util::getPHPErrorName($errno).') ';
        }

        $buf .= $message."\n";
        if (in_array($level, [LogLevel::ERROR, LogLevel::WARNING]))
            $buf .= ($stacktrace ?: Util::backtraceAsString(2))."\n";

        $set_perm = false;
        if (!file_exists($this->logFile)) {
            $set_perm = true;
            $dir = dirname($this->logFile);

            if (!file_exists($dir)) {
                mkdir($dir);
                setperm($dir);
            }
        }

        $f = fopen($this->logFile, 'a');
        if (!$f) {
            fprintf(STDERR, __METHOD__.': failed to open file \''.$this->logFile.'\' for writing');
            return;
        }

        fwrite($f, $buf);
        fclose($f);

        if ($set_perm)
            setperm($this->logFile);
    }
}