<?php


namespace iDServer\Message;


use DOMDocument;
use DOMElement;
use DOMXPath;
use iDServer\AbstractKeyStore;
use iDServer\Log;
use iDServer\Message\Strategy\AbstractMessageHandlingStrategy;
use iDServer\Saml\AttributeQueryData;
use iDServer\Saml\Status;
use iDServer\Constants;

class AttributeQuery extends AbstractMessage
{
    /**
     * @param AbstractKeyStore $keyStore
     * @param string $server
     * @param AttributeQueryData $data
     */
    public function __construct(AbstractKeyStore $keyStore, $server, AttributeQueryData $data)
    {
        parent::__construct($keyStore, $data);
        if (!$this->getData()->getDestination()) {
            $this->getData()->setDestination($server . '/jku/saml/attributequery');
        }
    }

    /**
     * @return string
     */
    public function getType()
    {
        return MessageType::ATTRIBUTE_QUERY;
    }

    /**
     * @param AbstractMessageHandlingStrategy $strategy
     * @return DOMDocument
     */
    protected function getUnsignedXml(AbstractMessageHandlingStrategy $strategy): DOMDocument
    {
        /* @var $data AttributeQueryData */
        $data = $this->getData();
        $doc = $strategy->createAttributeQuery($data);
        Log::debug("Constructed unsigned xml:\n" . $doc->saveXML());
        return $doc;
    }

    /**
     * @param DOMDocument $doc
     * @return array
     */
    public static function receiveMessage(DOMDocument $doc)
    {
        $xpath = new DOMXPath($doc);
        $xpath->registerNamespace('saml2p', Constants\NS_SAMLP);
        $xpath->registerNamespace('saml2', Constants\NS_SAML);

        $statusCode = $xpath
            ->query("saml2p:Status/saml2p:StatusCode[@Value]/@Value", $doc->documentElement)->item(0)
            ->nodeValue;

        $nodes = $xpath->query("./saml2p:Extensions/saml2:AttributeStatement/saml2:Attribute");
        $attribs = array();
        for ($i = 0; $i < $nodes->length; ++$i) {
            /* @var $node DOMElement */
            $node = $nodes->item($i);

            $name = $node->getAttribute('Name');

            /* @var $valNode DOMElement */
            $valNode = $node->getElementsByTagName('AttributeValue')->item(0);
            $value = !isset($valNode) || $valNode->getAttribute('nil') == 'true' ? null : $valNode->nodeValue;

            $attribs[] = [
                'Name' => $name,
                'Value' => $value
            ];
        }

        $result = [
            'Success' => ($statusCode === Status::SUCCESS),
            'MessageId' => $doc->documentElement->getAttribute('ID'),
            'MessageType' => MessageType::ATTRIBUTE_QUERY_RESPONSE,
            'XML' => $doc,
        ];

        if (!empty($assertions)) {
            $result['Assertion'] = $assertions[0];
        }
        if (!empty($attribs)) {
            $result['Attributes'] = $attribs;
        }


        Log::debug("Received message:\n" . $doc->saveXML());

        return $result;
    }
}
