<?php
/**
 * @package   BaForms
 * @author    Balbooa http://www.balbooa.com/
 * @copyright Copyright @ Balbooa
 * @license   http://www.gnu.org/licenses/gpl.html GNU/GPL
 */

namespace Balbooa\Component\Forms\Administrator\Helper\Filter\Abstracts;

use Balbooa\Component\Forms\Administrator\Helper\Filter\Enum\FilterEnum;
use Balbooa\Component\Forms\Administrator\Helper\Filter\Interface\FilterInterface;

defined('_JEXEC') or die;

abstract class AbstractFilter implements FilterInterface
{
    private static array $instances = [];

    protected array $rules = [];

    public static function getInstance(): static
    {
        $class = static::class;

        if (!isset(self::$instances[$class])) {
            self::$instances[$class] = new static();
        }

        return self::$instances[$class];
    }

    protected function cleanQuotesString(string $text): string
    {
        return htmlspecialchars($text, ENT_COMPAT, 'UTF-8');
    }

    protected function cleanString(string $text): string
    {
        $text = preg_replace("'<script[^>]*>.*?</script>'si", '', $text);
        $text = preg_replace('/<!--.+?-->/', '', $text);
        $text = preg_replace('/{.+?}/', '', $text);
        $text = preg_replace('/&nbsp;/', ' ', $text);
        $text = preg_replace('/&amp;/', ' ', $text);
        $text = preg_replace('/&quot;/', ' ', $text);
        $text = strip_tags($text);
        $text = str_replace(['"', "'"], '', $text);

        return $text;
    }

    protected function cleanBoolean(mixed $value): bool
    {
        return (bool) $value;
    }

    protected function cleanInteger(mixed $value): int
    {
        return (int) $value;
    }

    protected function cleanFloat(mixed $value): float
    {
        return (float) $value;
    }

    protected function validate(FilterEnum $rule, mixed $value): string|int|bool
    {
        return match ($rule) {
            FilterEnum::String => $this->cleanString($value),
            FilterEnum::Integer => $this->cleanInteger($value),
            FilterEnum::Boolean => $this->cleanBoolean($value),
            FilterEnum::Float => $this->cleanFloat($value),
            FilterEnum::QuotedString => $this->cleanQuotesString($value),
        };
    }

    protected function cleanData(array $rules, object &$data): void
    {
        foreach ($rules as $key => $rule) {
            if (!isset($data->$key)) {
                continue;
            }

            $data->$key = $this->validate($rule, $data->$key);
        }
    }

    public function clean(object &$data): void
    {
        $this->cleanData($this->rules, $data);
    }
}