<?php
namespace Fifa\ConnectServiceBus\Sdk\Message;

/**
 * Class Message
 * @package Fifa\ConnectServiceBus\Sdk\Message
 */
class Message
{
    const LOCK_TOKEN_KEY = 'LockToken';
    const MESSAGE_ID_KEY = 'MessageId';

    const SENDER_KEY = 'Sender';
    const REPLY_TO_KEY = 'ReplyTo';

    /**
     * @var string|null
     */
    private $content;

    /**
     * @var string|null
     */
    private $action;

    /**
     * @param array
     */
    private $brokerProperties;

    /**
     * @var array
     */
    private $properties;

    /**
     * Constructor
     *
     * @param string|null $content
     * @param string|null $action
     * @param array $properties
     * @param array $brokerProperties
     */
    public function __construct(?string $content, ?string $action = null, array $properties = array(), array $brokerProperties = array())
    {
        $this->content = $content;
        $this->action = $action;
        $this->properties = $properties;
        $this->brokerProperties = $brokerProperties;
    }

    /**
     * String representation of the object
     *
     * @return string
     */
    public function __toString()
    {
        $contentLength = is_null($this->content) ? -1 : strlen($this->content);
        return "Id: {$this->getId()}, Action: $this->action, ContentLength: $contentLength, Properties: {$this->dumpProperties($this->properties)}, BrokerProperties: {$this->dumpProperties($this->brokerProperties)}";
    }

    /**
     * @param array $properties
     * @return string
     */
    private function dumpProperties(array $properties): string
    {
        $propAsStrings = array();
        foreach ($properties as $key => $value) {
            $propAsStrings[] = $key . '=' . $value;
        }

        return join(', ', $propAsStrings);
    }

    /**
     * Gets message content
     *
     * @return string|null
     */
    public function getContent(): ?string
    {
        return $this->content;
    }

    /**
     * Gets message action type
     *
     * @return string
     */
    public function getAction(): ?string
    {
        return $this->action;
    }

    /**
     * Gets message properties
     *
     * @return array
     */
    public function getProperties(): array
    {
        return $this->properties;
    }

    /**
     * Gets property if it exists or null otherwise
     *
     * @return mixed
     */
    public function getPropertyIfExists(string $key)
    {
        if(array_key_exists($key, $this->properties)) {
            return $this->properties[$key];
        }
        return null;
    }

    /**
     * Gets message broker properties
     *
     * @return array
     */
    public function getBrokerProperties(): array
    {
        return $this->brokerProperties;
    }

    /**
     * Gets message id
     *
     * @return string|null
     */
    public function getId(): ?string
    {
        return $this->getBrokerProperty(self::MESSAGE_ID_KEY);
    }

    /**
     * Gets lock token
     *
     * @return string|null
     */
    public function getLockToken(): ?string
    {
        return $this->getBrokerProperty(self::LOCK_TOKEN_KEY);
    }

    /**
     * Gets sender
     *
     * @return string|null
     */
    public function getSender(): ?string
    {
        return $this->getBrokerProperty(self::SENDER_KEY);
    }

    /**
     * Gets `reply to` value
     *
     * @return string|null
     */
    public function getReplyTo(): ?string
    {
        return $this->getBrokerProperty(self::REPLY_TO_KEY);
    }

    /**
     * Gets broker property, if exists
     *
     * @param string $key
     * @return string|null
     */
    private function getBrokerProperty(string $key): ?string
    {
        return $this->brokerProperties[$key] ?? null;
    }

    /**
     * Sets the content of message
     *
     * @param string $content
     * @return Message
     */
    public function setContent(string $content): Message
    {
        $this->content = $content;
        return $this;
    }
}
