<?php

namespace traits;

use classes\db;

trait module_config_t
{
    public string $module_name; // The name of the module
    public array $config_classes; // An array of classes that contain config variables for the module, that's allowed to be updated by the user using the API

    /**
     * Set up the config variable
     * @param string $module_name
     * @return void
     */
    function setupConfig(string $module_name): void
    {
        $this->module_name = $module_name;
    }

    /**
     * Allow the user to update the config variables
     * @param array $config_classes
     * @return void
     */
    function allowUpdate(array $config_classes): void
    {
        $this->config_classes = $config_classes;
    }

    /**
     * Post config request
     * @return bool
     */
    function postConfigRequest(): bool
    {
        // Check if the request has a variable name and value
        global $response;
        if ($response->getRequestParameter('variable') === null || $response->getRequestParameter('value') === null) {
            $response->error('Variable and value not set', 400);
        }
        // Get the variable name and value
        $variable = $response->getRequestParameter('variable');
        $value = $response->getRequestParameter('value');
        // Sanitize the variable name and value
        global /** @var db $db */
        $db;
        $variable = $db->escape_string($variable);
        $value = $db->escape_string($value);
        // Check if the variable is allowed to be updated
        if (!self::isVariableAllowed($variable)) {
            // Return an error message, telling the user that the variable is not allowed to be updated. With a list of allowed variables
            $allowed_variables = [];
            foreach ( $this->config_classes as $config_class ) {
                $allowed_variables[] = (new $config_class())->getVariableName();
            }
            $allowed_variables = implode(', ', $allowed_variables);
            $response->error("Variable not allowed to be updated. Allowed variables: $allowed_variables", 400);
            return false;
        }
        // Update the config variable using the config class that contains the variable
        foreach ( $this->config_classes as $config_class ) {
            // Create a new instance of the config class
            $tmp = new $config_class();
            // Check if the variable matches the variable name in the config class
            if ($tmp->getVariableName() == $variable) {
                // Update the config variable
                $tmp->setVariableValue($value);
            }
        }

        // Return the updated config variable
        return true;
    }

    /**
     * Check if the variable is allowed to be updated
     * @param string $variable
     * @return bool
     */
    function isVariableAllowed(string $variable): bool
    {
        foreach ( $this->config_classes as $config_class ) {
            // Create a new instance of the config class
            $tmp = new $config_class();
            // Check if the variable matches the variable name in the config class
            if ($tmp->getVariableName() == $variable) {
                return true;
            }
        }
        return false;
    }


    function getConfigRequest(): array
    {
        // Get the config variable
        global /** @var db $db */
        $db;
        // Check if the request has a variable name
        if (!isset($_GET['variable'])) {
            return self::getConfig();
        }
        // Get the variable name
        $variable = $_GET['variable'];
        // Sanitize the variable name
        $variable = $db->escape_string($variable);
        // Get the config variable
        $sql = "SELECT * FROM module_config WHERE module = '$this->module_name' AND variable = '$variable'";
        return $this->extracted($db, $sql);
    }

    /**
     * Get all config variables for the module
     * @return array
     */
    function getConfig(): array
    {
        global $db;
        $sql = "SELECT * FROM module_config WHERE module = '$this->module_name'";
        return $this->extracted($db, $sql);
    }


    /**
     * @param $db
     * @param string $sql
     * @return array
     */
    private function extracted($db, string $sql): array
    {
        $result = $db->query($sql);
        $config = [];
        while ($row = $result->fetch_assoc()) {
            $config[] = [
                'module' => $row['module'],
                'variable' => $row['variable'],
                'type' => $row['type'],
                'value' => $this->parseConfigVariableType($row['type'], $row['value'])
            ];
        }
        return $config;
    }

    function parseConfigVariableType($type, $value)
    {
        // If the variable is an int, convert it to an int
        if ($type == 'integer' || $type == 'int') {
            return (integer)$value;
        }
        // If the variable is a boolean, convert it to a boolean
        if ($type == 'bool') {
            return $value == 'true';
        }
        // If the variable is a float, convert it to a float
        if ($type == 'float') {
            return (float)$value;
        }
        // If the variable is a JSON string, convert it to an array
        if ($type == 'json') {
            return json_decode($value, true);
        }
        // If the variable is a string, convert it to a string
        if ($type == 'string') {
            return (string)$value;
        }
        // If the variable is an array, convert it to an array
        if ($type == 'array') {
            return explode(',', $value);
        }
        // If the variable is a date, convert it to a date
        if ($type == 'date') {
            return date('Y-m-d', strtotime($value));
        }
        // If the variable is a time, convert it to a time
        if ($type == 'time') {
            return date('H:i:s', strtotime($value));
        }
        // If the variable is a datetime, convert it to a datetime
        if ($type == 'datetime') {
            return date('Y-m-d H:i:s', strtotime($value));
        }
        // If the variable is a timestamp, convert it to a timestamp
        if ($type == 'timestamp') {
            return strtotime($value);
        }
        return $value;
    }

    /**
     * Get the module name
     * @return string
     */
    function getModuleName(): string
    {
        return $this->module_name;
    }
}