<?php

namespace Dalten\RuianToUir\Formatter;

use Dalten\RuianToUir\Converter\Field\GeometryFieldInterface;

/**
 * Formatter, který převádí hodnoty do formátu SQL pro mysql.
 *
 * Escapování je řešeno dost humpolácky, takže pozor. :)
 */
class Sql implements FormatterInterface
{
    /**
     * Mapa názvu formatteru na primární klíč (ident) položky.
     *
     * @var array
     */
    private $formatterNameToIdentifierMap = [];

    /**
     * Mapa názvu formatteru na název tabulky v DB.
     *
     * @var array
     */
    private $formatterNameToTableNameMap = [];

    /**
     * Sql constructor.
     *
     * @param array $formatterNameToTableNameMap
     * @param array $formatterNameToIdentifierMap
     */
    public function __construct(array $formatterNameToTableNameMap, array $formatterNameToIdentifierMap)
    {
        $this->formatterNameToIdentifierMap = $formatterNameToIdentifierMap;
        $this->formatterNameToTableNameMap = $formatterNameToTableNameMap;
    }

    /**
     * Zformátuje data na jeden sql dotaz.
     *
     * @param array  $data          Pole převedených dat.
     * @param string $converterName Název converteru, který provedl převod.
     *
     * @return string Výsledný dotaz.
     */
    public function format(array $data, $converterName)
    {
        if ('RemovedItem' === $converterName) {
            $converterName = $data['parent_converter'];
            $identName = $this->_getIdentifierName($converterName);
            $tableName = $this->_getTableName($converterName);

            return sprintf(
                'UPDATE `%s` SET `stav` = 0 WHERE `%s` = %d LIMIT 1;', $tableName, $identName, $data['identifier']
            );
        } else {
            $fieldNames = $values = [];
            foreach ($data as $column => $value) {
                if ($value instanceof GeometryFieldInterface) {
                    $fieldNames[] = "`$column`";
                    $values[] = 'ST_GeomFromText(\''.$value->getWKT().'\')';
                } else {
                    $fieldNames[] = "`$column`";
                    $values[] = "'".addslashes($value)."'";
                }
            }

            return sprintf(
                'REPLACE INTO `%s` (%s) VALUES (%s);', $this->_getTableName($converterName),
                implode(', ', $fieldNames), implode(', ', $values)
            );
        }
    }

    /**
     * Převede název formatteru na název tabulky.
     *
     * @param string $converterName Název converteru, který provedl převod.
     *
     * @return string Název tabulky.
     *
     * @throws \InvalidArgumentException Pokud tabulka pro daný prvek není namapována.
     */
    private function _getTableName($converterName)
    {
        if (isset($this->formatterNameToTableNameMap[$converterName])) {
            return $this->formatterNameToTableNameMap[$converterName];
        }

        throw new \InvalidArgumentException(
            sprintf('Typ converteru "%s" není podporován SQL formatterem.', $converterName)
        );
    }

    /**
     * Převede název formatteru na název primárního klíče (idenfikátoru).
     *
     * @param string $converterName Název converteru, který provedl převod.
     *
     * @return string Název primárního klíče (idenfikátoru).
     *
     * @throws \InvalidArgumentException Pokud tabulka pro daný prvek není namapována.
     */
    private function _getIdentifierName($converterName)
    {
        if (isset($this->formatterNameToIdentifierMap[$converterName])) {
            return $this->formatterNameToIdentifierMap[$converterName];
        }

        throw new \InvalidArgumentException(
            sprintf('Typ converteru "%s" není podporován SQL formatterem.', $converterName)
        );
    }
}
