<?php
namespace Misuzu\Config;

use Index\Data\DataException;
use Index\Data\IDbConnection;
use Index\Data\IDbStatement;

class DbConfig implements IConfig {
    private IDbConnection $dbConn;
    private array $values = [];

    private ?IDbStatement $stmtSet = null;
    private ?IDbStatement $stmtDelete = null;

    public function __construct(IDbConnection $dbConn) {
        $this->dbConn = $dbConn;
    }

    public function reload(): void {
        $this->values = [];

        try {
            $result = $this->dbConn->query('SELECT config_name, config_value FROM msz_config;');
            while($result->next())
                $this->values[$result->getString(0)] = unserialize($result->getString(1));
        } catch(DataException $ex) { }
    }

    public function scopeTo(string $prefix): IConfig {
        return new ScopedConfig($this, $prefix);
    }

    public function getNames(): array {
        return array_keys($this->values);
    }

    public function getValue(string $name, string $type = CfgType::T_ANY, $default = null): mixed {
        $value = $this->values[$name] ?? null;

        if($type !== CfgType::T_ANY && CfgTools::type($value) !== $type)
            $value = null;

        return $value ?? $default ?? CfgTools::default($type);
    }

    public function hasValue(string $name): bool {
        return array_key_exists($name, $this->values);
    }

    public function setValue(string $name, $value, bool $save = true): void {
        $this->values[$name] = $value;

        if($save) {
            $value = serialize($value);

            if($this->stmtSet === null)
                $this->stmtSet = $this->dbConn->prepare('REPLACE INTO msz_config (config_name, config_value) VALUES (?, ?)');

            $this->stmtSet->reset();
            $this->stmtSet->addParameter(1, $name);
            $this->stmtSet->addParameter(2, $value);
            $this->stmtSet->execute();
        }
    }

    public function removeValue(string $name, bool $save = true): void {
        unset($this->values[$name]);

        if($save) {
            if($this->stmtDelete === null)
                $this->stmtDelete = $this->dbConn->prepare('DELETE FROM msz_config WHERE config_name = ?');

            $this->stmtDelete->reset();
            $this->stmtDelete->addParameter(1, $name);
            $this->stmtDelete->execute();
        }
    }
}
