<?php

namespace iDServer\Message;

use DOMDocument;
use Exception;
use iDServer\AbstractKeyStore;
use iDServer\Internal\Crypto;
use iDServer\Log;
use iDServer\Message\Strategy\AbstractMessageHandlingStrategy;
use iDServer\Saml\AbstractSamlData;

abstract class AbstractMessage
{
    /**
     * @var AbstractKeyStore
     */
    protected $keyStore;

    /**
     * @var null|string
     */
    protected $language = null;

    /**
     * @var AbstractSamlData
     */
    private $data;

    /**
     *
     * @param AbstractKeyStore|null $keyStore
     * @param AbstractSamlData|null $data
     */
    public function __construct(AbstractKeyStore $keyStore = null, AbstractSamlData $data = null)
    {
        $this->keyStore = $keyStore;
        $this->data = $data;
    }

    /**
     * @return string
     */
    abstract public function getType();

    /**
     * @return string|null
     */
    public function getLanguage()
    {
        return $this->language;
    }

    /**
     * @param string $lang
     * @return $this
     */
    public function setLanguage($lang)
    {
        $this->language = $lang;
        return $this;
    }

    /**
     * Get the DOMDocument instance of the XML
     *
     * @param AbstractMessageHandlingStrategy $strategy
     * @return DOMDocument
     */
    abstract protected function getUnsignedXml(AbstractMessageHandlingStrategy $strategy);

    /**
     * Get the DOMDocument instance of the signed XML message
     *
     * @param AbstractMessageHandlingStrategy $strategy
     * @return DOMDocument
     * @throws Exception
     */
    public function getSignedXml(AbstractMessageHandlingStrategy $strategy)
    {
        $doc = $this->getUnsignedXml($strategy);
        $key = $this->keyStore->getSigningKey();
        $cert = $this->keyStore->getSigningCertificate();
        $doc = Crypto\sign($doc, $key, $cert);

        Log::debug("Signed XML: " . $doc->saveXML());
        return $doc;
    }

    /**
     * @return AbstractSamlData|null
     */
    public function getData()
    {
        return $this->data;
    }
}
