<?php

namespace Fifa\ConnectId\Sdk\Tms\MessageHandlers;

use Fifa\ConnectId\Sdk\MessageHandlers\MessageHandlerInterface;
use Fifa\ConnectId\Sdk\MessageHandlers\MessageHandlersUtil;
use Fifa\ConnectId\Sdk\Registration\CorrelationIdBasedItemContainerInterface;
use Fifa\ConnectId\Sdk\Registration\ValidationException;
use Fifa\ConnectId\Sdk\Util\Builder\Error\CompositeErrorBuilder;
use Fifa\ConnectId\Sdk\Util\Data\Message\MessageProperties;
use Fifa\ConnectId\Sdk\Util\StringUtils;
use Fifa\ConnectServiceBus\Sdk\Message\Message;

class CorrelationIdContainerBasedMessageHandler implements MessageHandlerInterface
{
    /**
     * @var CorrelationIdBasedItemContainerInterface
     */
    private $responsesCache;

    /**
     * @var string
     */
    private $handledMessageType;

    /**
     * @var callable
     */
    private $messageFactory;

    /**
     * @param string $handledMessageType
     * @param CorrelationIdBasedItemContainerInterface $responsesCache
     * @param callable $messageFactory
     */
    public function __construct(string $handledMessageType, CorrelationIdBasedItemContainerInterface $responsesCache, callable $messageFactory)
    {
        $this->responsesCache = $responsesCache;
        $this->handledMessageType = $handledMessageType;
        $this->messageFactory = $messageFactory;
    }

    /**
     * @inheritDoc
     */
    public function canHandle(?string $messageType): bool
    {
        return $messageType == $this->handledMessageType;
    }

    /**
     * @inheritDoc
     */
    public function handle(?string $messageType, Message $message)
    {
        $correlationId = $message->getPropertyIfExists(MessageProperties::CORRELATION_ID);

        $errorBuilder = new CompositeErrorBuilder();
        $errors = $errorBuilder
            ->addMessageForCase(StringUtils::isNullOrEmpty($correlationId), 'The "'.MessageProperties::CORRELATION_ID.'" property cannot be null or empty.')
            ->build();

        if (!is_null($errors)) {
            throw new ValidationException($errors);
        }

        $xmlData = $message->getContent();
        $this->responsesCache->put($correlationId, call_user_func_array($this->messageFactory, [$xmlData]));
    }

    /**
     * String representation of the object
     */
    public function __toString()
    {
        return MessageHandlersUtil::FullNameWithMessageType($this, $this->handledMessageType);
    }
}