<?php

/**
 * SPDX-FileCopyrightText: 2024 Sascha Nitsch (grumpydeveloper) https://contentnation.net/@grumpydevelop
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
 * @author Author: Sascha Nitsch (grumpydeveloper)
 **/

 namespace Federator;

/**
 * Base class for Api and related classes
 * @author Sascha Nitsch
 */
class Main
{
    /**
     * cache instance
     *
     * @var Cache\Cache $cache
     */
    protected $cache;
    /**
     * current config
     *
     * @var array<string,mixed>  $config
     */
    protected $config;
    /**
     * remote connector
     *
     * @var Connector\Connector $connector
     */
    protected $connector = null;
    /**
     * response content type
     *
     * @var string $contentType
     */
    protected $contentType = "text/html";
    /**
     * database instance
     *
     * @var \Mysqli $dbh
     */
    protected $dbh;
    /**
     * extra headers
     *
     * @var array<string,string>  $headers
     */
    protected $headers = [];
    /**
     * languange instance
     *
     * @var Language $lang
     */
    protected $lang = null;
    /**
     * redirect URL
     *
     * @var ?string $redirect
     */
    protected $redirect = null;
    /**
     * response code
     *
     * @var int $responseCode
     */
    protected $responseCode = 200;
    /**
     * smarty instance
     *
     * @var \Smarty\Smarty|null $smarty
     */
    protected $smarty;

    /**
     * constructor
     *
     * @param string $rootDir root directory
     */
    public function __construct($rootDir = '../')
    {
        $this->responseCode = 200;
        $config = parse_ini_file($rootDir . 'config.ini', true);
        if ($config !== false) {
            $this->config = $config;
        }
    }

    /**
     * do a remote call and return results
     * @param string $remoteURL remote URL
     * @param string[]|null $headers optional headers to send
     * @return array{string, mixed} response and status information
     */
    public static function getFromRemote(string $remoteURL, $headers)
    {
        $ch = curl_init();
        if ($ch === false) {
            return ['', null];
        }
        curl_setopt($ch, CURLOPT_URL, $remoteURL);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        if ($headers !== null) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }
        curl_setopt($ch, CURLOPT_VERBOSE, true);
        curl_setopt($ch, CURLINFO_HEADER_OUT, true);
        $ret = curl_exec($ch);
        $info = curl_getinfo($ch);
        curl_close($ch);
        return [$ret, $info];
    }

    /**
     * get config
     * @return Array<String, Mixed>
     */
    public function getConfig()
    {
        return $this->config;
    }

    /**
     * get database handle
     *
     * @return \mysqli|false database handle
     */
    public function getDatabase()
    {
        return $this->dbh;
    }

    /**
     * load plugins
     */
    public function loadPlugins() : void
    {
        if (array_key_exists('plugins', $this->config)) {
            $plugins = $this->config['plugins'];
            foreach ($plugins as $name => $file) {
                require_once($file);
                $fktn = 'Federator\\' . $name . '_load';
                if (function_exists($fktn)) {
                    $fktn($this);
                }
            }
        }
    }

    /**
     * open database
     *
     * @param string|null $usernameOverride optional username override
     * @param string|null $passwordOverride optional password override
     * @return void
     */
    public function openDatabase($usernameOverride = null, $passwordOverride = null)
    {
        $dbconf = $this->config["database"];
        $this->dbh = new \mysqli(
            $dbconf['host'],
            $usernameOverride ?? (string)$dbconf['username'],
            $passwordOverride ?? (string)$dbconf['password'],
            $dbconf['database']
        );
        if ($this->dbh->connect_error !== null) {
            http_response_code(500);
            die('Database Connect Error');
        }
    }

    /**
     * set cache
     */
    public function setCache(Cache\Cache $cache) : void
    {
        $this->cache = $cache;
    }

    /**
     * set connector
     */
    public function setConnector(Connector\Connector $connector) : void
    {
        $this->connector = $connector;
    }

    /**
     * set response code
     *
     * @param int $code
     *          new response code
     */
    public function setResponseCode(int $code) : void
    {
        $this->responseCode = $code;
    }

    /**
     * translate given group and key using given language
     *
     * @param ?string $lang
     *          language to use
     * @param string $group
     *          language group to use
     * @param string $key
     *          language key to use
     * @param mixed[] $parameters
     *          optional parameters
     * @return string translation
     */
    public function translate(?string $lang, string $group, string $key, array $parameters = array()) : string
    {
        if ($this->lang === null) {
            $this->validLanguage($lang);
        }
        if ($this->lang !== null) {
            if ($this->lang->getLang() !== $lang) {
                $l = new Language($lang);
                return $l->printlang($group, $key, $parameters);
            }
            return $this->lang->printlang($group, $key, $parameters);
        } else {
            return $key;
        }
    }

    /**
     * check if language is valid by loading it
     *
     * @param ?string $lang
     */
    public function validLanguage(?string $lang) : bool
    {
        $language = new Language($lang);
        if ($language->getLang() === $lang) {
            $this->lang = $language;
            return true;
        }
        return false;
    }
}