<?php

namespace FiloBlu\Refilo\Remote\Connector;

use FiloBlu\Core\Framework\Model\AbstractSqlRepository;
use Magento\Framework\Api\Search\SearchCriteriaInterfaceFactory;
use Magento\Framework\Api\SearchResultsInterfaceFactory;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\DataObjectFactory;
use Magento\Framework\Serialize\SerializerInterface;

/**
 * Class ConnectorRepository
 * @package FiloBlu\Refilo\Remote\Connector
 */
class ConnectorConfigurationRepository extends AbstractSqlRepository implements ConnectorConfigurationRepositoryInterface
{
    /**
     * @var ConnectorPool
     */
    private $connectorPool;
    /**
     * @var DataObjectFactory
     */
    private $dataObjectFactory;
    /**
     * @var SerializerInterface
     */
    private $serializer;
    /**
     * @var ConnectorConfigurationInterfaceFactory
     */
    private $connectorConfigurationFactory;

    /**
     * ConnectorRepository constructor.
     * @param ConnectorPool $connectorPool
     * @param DataObjectFactory $dataObjectFactory
     * @param SerializerInterface $serializer
     * @param ResourceConnection $resourceConnection
     * @param ConnectorConfigurationInterfaceFactory $connectorConfigurationFactory
     * @param SearchCriteriaInterfaceFactory $searchCriteriaFactory
     * @param SearchResultsInterfaceFactory $searchResultsFactory
     */
    public function __construct(
        ConnectorPool $connectorPool,
        DataObjectFactory $dataObjectFactory,
        SerializerInterface $serializer,
        ResourceConnection $resourceConnection,
        ConnectorConfigurationInterfaceFactory $connectorConfigurationFactory,
        SearchCriteriaInterfaceFactory $searchCriteriaFactory,
        SearchResultsInterfaceFactory $searchResultsFactory
    ) {
        parent::__construct($resourceConnection, $searchCriteriaFactory, $searchResultsFactory);
        $this->connectorPool = $connectorPool;
        $this->dataObjectFactory = $dataObjectFactory;
        $this->serializer = $serializer;
        $this->connectorConfigurationFactory = $connectorConfigurationFactory;
    }

    /**
     * @param ConnectorConfigurationInterface $connectorConfiguration
     * @return ConnectorConfigurationInterface
     */
    public function save(ConnectorConfigurationInterface $connectorConfiguration): ConnectorConfigurationInterface
    {
        $connection = $this->resourceConnection->getConnection();
        $table = $connection->getTableName(self::TABLE_NAME);

        $connectorId = $connectorConfiguration->getId();

        $bindings = [
            ConnectorConfigurationInterface::NAME          => $connectorConfiguration->getName(),
            ConnectorConfigurationInterface::TYPE          => $this->connectorPool->getTypeFor($connectorConfiguration->getConnector()),
            ConnectorConfigurationInterface::CONFIGURATION => $connectorConfiguration->getConfiguration()->toJson()
        ];

        if ($connectorId) {
            $connection->update($table, $bindings, $connection->quoteInto(sprintf('%s = ?', ConnectorConfigurationInterface::ID), $connectorId));
        } else {
            $connection->insert($table, $bindings);
            $connectorConfiguration->setId($connection->lastInsertId($table));
        }

        return $connectorConfiguration;
    }

    /**
     * @return string
     */
    public function getTable(): string
    {
        return self::TABLE_NAME;
    }

    /**
     * @return string
     */
    public function getIdFieldName(): string
    {
        return ConnectorConfigurationInterface::ID;
    }

    /**
     * @param array $row
     * @return mixed|void
     */
    public function fromRow(array $row)
    {
        $connector = $this->connectorPool->get($row[ConnectorConfigurationInterface::TYPE]);
        $configuration = $this->dataObjectFactory->create();
        $configuration->setData($this->serializer->unserialize($row[ConnectorConfigurationInterface::CONFIGURATION]));

        $connectorConfiguration = $this->connectorConfigurationFactory->create();

        return $connectorConfiguration
            ->setName($row[ConnectorConfigurationInterface::NAME])
            ->setConnector($connector)
            ->setConfiguration($configuration)
            ->setId($row[ConnectorConfigurationInterface::ID]);
    }
}
