<?php

namespace FiloBlu\Esb\Controller\Adminhtml\Consumer;

use Exception;
use FiloBlu\Esb\Api\ConsumerConfigurationRepositoryInterface;
use FiloBlu\Esb\Api\ConsumerResolverInterface;
use FiloBlu\Esb\Api\Data\ConsumerConfigurationInterface;
use FiloBlu\Esb\Api\Data\ConsumerConfigurationInterfaceFactory;
use FiloBlu\Esb\Api\RetryStrategyResolverInterface;
use FiloBlu\Esb\Controller\Adminhtml\Common\AbstractEdit;
use FiloBlu\Esb\Converter\JsonToDataObject;
use FiloBlu\Esb\Model\ObjectTypeLoaderResolverInterface;
use FiloBlu\Esb\Model\ObjectTypeSaverResolver;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\View\Result\PageFactory;

/**
 * Class Edit
 * @package FiloBlu\Esb\Controller\Adminhtml\Consumer
 */
class Edit extends AbstractEdit
{
    /**
     * @var PageFactory
     */
    protected $resultPageFactory;
    /**
     * @var ConsumerConfigurationInterfaceFactory
     */
    private $consumerConfigurationFactory;
    /**
     * @var ConsumerConfigurationRepositoryInterface
     */
    private $consumerConfigurationRepository;
    /**
     * @var JsonToDataObject
     */
    private $jsonToDataObject;
    /**
     * @var RetryStrategyResolverInterface
     */
    private $strategyResolver;
    /**
     * @var ConsumerResolverInterface
     */
    private $consumerResolver;
    /**
     * @var ObjectTypeLoaderResolverInterface
     */
    private $loaderResolver;
    /**
     * @var ObjectTypeSaverResolver
     */
    private $saverResolver;

    /**
     * Constructor
     *
     * @param Context $context
     * @param JsonToDataObject $jsonToDataObject
     * @param ConsumerConfigurationInterfaceFactory $consumerConfigurationFactory
     * @param ConsumerConfigurationRepositoryInterface $consumerConfigurationRepository
     * @param RetryStrategyResolverInterface $strategyResolver
     * @param ConsumerResolverInterface $consumerResolver
     * @param PageFactory $resultPageFactory
     * @param ObjectTypeLoaderResolverInterface $loaderResolver
     * @param ObjectTypeSaverResolver $saverResolver
     */
    public function __construct(
        Context $context,
        JsonToDataObject $jsonToDataObject,
        ConsumerConfigurationInterfaceFactory $consumerConfigurationFactory,
        ConsumerConfigurationRepositoryInterface $consumerConfigurationRepository,
        RetryStrategyResolverInterface $strategyResolver,
        ConsumerResolverInterface $consumerResolver,
        PageFactory $resultPageFactory,
        ObjectTypeLoaderResolverInterface $loaderResolver,
        ObjectTypeSaverResolver $saverResolver
    ) {
        parent::__construct($context);
        $this->consumerConfigurationFactory = $consumerConfigurationFactory;
        $this->consumerConfigurationRepository = $consumerConfigurationRepository;
        $this->resultPageFactory = $resultPageFactory;
        $this->jsonToDataObject = $jsonToDataObject;
        $this->strategyResolver = $strategyResolver;
        $this->consumerResolver = $consumerResolver;
        $this->loaderResolver = $loaderResolver;
        $this->saverResolver = $saverResolver;
    }

    /**
     * Execute view action
     *
     * @return ResultInterface
     */
    public function execute()
    {
        $general = $this->getRequest()->getParam('general');

        $consumer = $general['consumer'] ?? null;

        if ($consumer !== null && is_array($consumer)) {
            $id = $consumer[ConsumerConfigurationInterface::ID] ?? null;

            try {
                $strategy = $consumer[ConsumerConfigurationInterface::RETRY_STRATEGY];
                $parameters = $consumer[ConsumerConfigurationInterface::PARAMETERS];
                /** @var ConsumerConfigurationInterface $consumerObject */
                $consumerObject = $this->consumerConfigurationFactory->create();

                $consumerObject
                    ->setObjectLoader($this->loaderResolver->get($consumer[ConsumerConfigurationInterface::OBJECT_LOADER]))
                    ->setObjectSaver($this->saverResolver->get($consumer[ConsumerConfigurationInterface::OBJECT_SAVER]))
                    ->setSaveRequest($consumer[ConsumerConfigurationInterface::SAVE_REQUEST])
                    ->setSaveResponse($consumer[ConsumerConfigurationInterface::SAVE_RESPONSE])
                    ->setPriority($consumer[ConsumerConfigurationInterface::PRIORITY])
                    ->setTriggerDelay($consumer[ConsumerConfigurationInterface::TRIGGER_DELAY])
                    ->setOutputEvent($consumer[ConsumerConfigurationInterface::OUTPUT_EVENT])
                    ->setBindingEvent($consumer[ConsumerConfigurationInterface::BINDING_EVENT])
                    ->setConsumer($this->consumerResolver->get($consumer[ConsumerConfigurationInterface::CONSUMER]))
                    ->setLabel($consumer[ConsumerConfigurationInterface::LABEL])
                    ->setId($id)
                    ->setUuid($consumer[ConsumerConfigurationInterface::UUID]);
                if ($strategy) {
                    $consumerObject->setRetryStrategy($this->strategyResolver->get($strategy));
                }

                if ($consumer[ConsumerConfigurationInterface::ENABLE]) {
                    $consumerObject->enable();
                } else {
                    $consumerObject->disable();
                }

                $consumerObject->setParameters($this->jsonToDataObject->convert($parameters));

                $this->consumerConfigurationRepository->save($consumerObject);
                $id = $consumerObject->getId();
                $this->messageManager->addSuccessMessage('Save success');
            } catch (Exception $exception) {
                $this->messageManager->addExceptionMessage($exception);
            }

            return $this->getRedirectPath($id);
        }

        return $this->resultPageFactory->create();
    }
}
