<?php

namespace Axioma\Server;

use Axioma\Utils as utils;

class App
{
    use AppConfig;
    use Protocol;
    use AppDB;

    public static function version()
    {
        return '5.1';
    }

    public static function completeName()
    {
        return _('Сервер лицензий ГИС Аксиома') . ' ' . self::version();
    }

    public function __construct()
    {
        $this->initAppConfig();
        $config = \Axioma\Config::instance();
        if (isset($config->app_root)) {
            $this->root = $config->app_root;
        }
        if (isset($config->app_ini)) {
            $this->ini = $config->app_ini;
        }
        $this->loadAppConfig();
        if (isset($config->app_port)) {
            $this->setAppPort($config->app_port);
        }
        if (isset($config->license_path)) {
            $this->setLicensePath($config->license_path);
        }
        if (isset($config->serial)) {
            $this->setSerialNumber($config->serial);
        }
        if (isset($config->company)) {
            $this->setCompany($config->company);
        }
    }

    public function getLogTail($lines = null, $time_diff = null, &$error = null)
    {
        usleep(2000);
        $path = $this->logPath();
        if (!is_file($path)) {
            $error = _("Файл журнала '$path' не найден");
            return false;
        }
        if ($lines === null || $lines < 0) {
            $lines = 0;
        }
        if ($lines === 0 && !$time_diff) {
            return file($this->logPath());
        }

        $f = fopen($path, "rb");
        if ($f === false) {
            return false;
        }

        $buffer = ($lines === 0 || $lines > 10) ? 4096 : ($lines === 1 ? 128 : 512);
        fseek($f, 0, SEEK_END);

        $output = array();
        $last_chunk = '';

        $filtered = false;
        $time_filter = function ($line) use ($time_diff, &$filtered) {
            if (strlen($line) < 19 || $time_diff === null) {
                return false;
            }
            $date_str = substr($line, 0, 19);
            $line_date = \DateTime::createFromFormat('Y-m-d\TH:i:s', $date_str);
            $now = new \DateTime();
            $start = $now->sub($time_diff);
            $filtered = $filtered || ($line_date !== false && $line_date < $start);
            return ($line_date !== false && $line_date >= $start);
        };

        while (ftell($f) > 0) {
            $seek = min(ftell($f), $buffer);
            fseek($f, -$seek, SEEK_CUR);
            $last_chunk = fread($f, $seek) . $last_chunk;
            fseek($f, -$seek, SEEK_CUR);

            $chunk_lines = explode(PHP_EOL, $last_chunk);
            $last_chunk = array_shift($chunk_lines);
            if ($time_diff !== null && !empty($chunk_lines)) {
                $chunk_lines = array_filter($chunk_lines, $time_filter);
            }
            if (!empty($chunk_lines)) {
                $output = array_merge($chunk_lines, $output);
            }
            if ($lines > 0 && count($output) >= $lines) {
                $output = array_slice($output, -$lines);
            }
            if ($filtered || ($lines > 0 && count($output) >= $lines)) {
                break;
            }
        }
        fclose($f);
        if ($time_diff !== null && !$filtered && $time_filter($last_chunk)) {
            $output = array_unshift($output, $last_chunk);
        }
        return $output;
    }
}
