<?php

namespace Velis\Filter;

use Velis\Filter;

abstract class AbstractParamsConverter
{
    protected Filter $filter;

    /**
     * Param mapping from => to
     *
     * @var array<string, string>
     */
    protected array $map = [];

    /**
     * List of keys to remove
     *
     * @var array<string>|null
     */
    protected ?array $remove = null;

    /**
     * Params
     *
     * @var array<string, mixed>
     */
    protected array $params = [];

    public function __construct(Filter $filter)
    {
        $this->filter = $filter;
        $this->remove = $this->getParamsToRemove();
        $this->map = $this->getParamsMap();
    }

    /**
     * Does the removal and mapping by default, reimplement if some other operations are required
     *
     * @return self
     */
    public function convert(): self
    {
        return $this->remove()->map();
    }

    public function setParams(array $params): self
    {
        $this->params = $params;

        return $this;
    }

    public function getParams(): array
    {
        return $this->params;
    }

    protected function remove(): self
    {
        if ($this->remove) {
            foreach ($this->remove as $key) {
                if (isset($this->params[$key])) {
                    unset($this->params[$key]);
                }
            }
        }

        return $this;
    }

    protected function map(): self
    {
        foreach ($this->map as $from => $to) {
            if (isset($this->params[$from])) {
                $this->params[$to] = $this->params[$from];
                $this->filter[$to] = $this->params[$from];
                unset($this->params[$from]);
            }
        }

        return $this;
    }

    /**
     * Returns the list of params to remove, an empty array by default
     *
     * @return array<string>
     */
    protected function getParamsToRemove(): array
    {
        return [];
    }

    /**
     * Returns the param mapping array of pairs old_param => new_param
     *
     * @return array<string, string>
     */
    abstract protected function getParamsMap(): array;
}
