<?php

namespace FiloBlu\Esb\Core\Extractor;

use FiloBlu\Esb\Api\Data\MessageInterface;
use FiloBlu\Esb\Api\Data\ObjectTypeInterface;
use FiloBlu\Esb\Api\ObjectTypeDescriptorResolverInterface;
use FiloBlu\Esb\Model\ObjectType\ObjectTypeFactory;
use Magento\Framework\Exception\NoSuchEntityException;
use RuntimeException;

/**
 * Class ObjectTypeFromMessage
 * @package FiloBlu\Esb\Core\Extractor
 */
class ObjectTypeFromMessage
{
    /**
     * @var string
     */
    const OBJECT_TYPE_PATH = 'object_type';

    /**
     * @var string
     */
    const OBJECT_ID_PATH = 'object_id';

    /**
     * @var ObjectTypeDescriptorResolverInterface
     */
    private $descriptorResolver;

    /**
     * @var ObjectTypeFactory
     */
    private $objectTypeFactory;

    /**
     * ObjectTypeFromMessage constructor.
     * @param ObjectTypeFactory $objectTypeFactory
     * @param ObjectTypeDescriptorResolverInterface $descriptorResolver
     */
    public function __construct(
        ObjectTypeFactory $objectTypeFactory,
        ObjectTypeDescriptorResolverInterface $descriptorResolver
    ) {
        $this->descriptorResolver = $descriptorResolver;
        $this->objectTypeFactory = $objectTypeFactory;
    }

    /**
     * @param MessageInterface $message
     * @return ObjectTypeInterface
     * @throws NoSuchEntityException
     */
    public function extract(MessageInterface $message): ObjectTypeInterface
    {
        $typeCode = $message->getPayload()->getDataByPath(self::OBJECT_TYPE_PATH);
        $id = $message->getPayload()->getDataByPath(self::OBJECT_ID_PATH);

        if ($id === null) {
            throw new RuntimeException(sprintf('%s can not be null', self::OBJECT_ID_PATH));
        }

        return $this->objectTypeFactory->create([
            'id' => $message->getPayload()->getDataByPath(self::OBJECT_ID_PATH),
            'typeCode' => $this->descriptorResolver->get($typeCode)->getTypeCode()
        ]);
    }

    /**
     * @param $data
     * @return bool
     */
    public function isObjectType($data) : bool {

        if(is_array($data)) {
            return isset($data[self::OBJECT_TYPE_PATH], $data[self::OBJECT_ID_PATH]);
        }

        return false;
    }
}
