<?php

/*
 * This file is part of the AuthStack project.
 *
 * (c) Buckhill Ltd <development@buckhill.co.uk>
 *
 * This source file is subject to the Buckhill license that is bundled
 * with this source code in the file LICENSE.
 */

namespace AuthStack\SP;


use function Buckhill\config;
use LightSaml\SamlConstants;
use LightSaml\Credential\X509Certificate;
use LightSaml\Model\Metadata\KeyDescriptor;
use LightSaml\Model\Metadata\ContactPerson;
use LightSaml\Model\Metadata\SpSsoDescriptor;
use LightSaml\Model\Metadata\EntityDescriptor;
use LightSaml\Model\Metadata\SingleLogoutService;
use LightSaml\Model\Context\SerializationContext;
use LightSaml\Model\Metadata\AssertionConsumerService;

class Metadata
{
    protected $entity;

    public function __construct(array $config)
    {
        config()->set('Metadata', $config);

        $this->create();
    }


    /**
     *
     */
    public function toXml()
    {
        $serializationContext = new SerializationContext();

        $this->getEntity()->serialize($serializationContext->getDocument(), $serializationContext);

        return $serializationContext->getDocument()->saveXML();
    }


    /**
     * @return EntityDescriptor
     */
    protected function getEntity()
    {
        return $this->entity;
    }

    /**
     *
     */
    protected function create()
    {
        $entity = new EntityDescriptor(config('Metadata.SP.entityId'));
        $sp = new SpSsoDescriptor();

        $sp->setWantAssertionsSigned(config('Metadata.SP.wantsSignedAssertions', false));

        $sp->addNameIDFormat(config('Metadata.SP.nameIdFormat', SamlConstants::NAME_ID_FORMAT_NONE));

        $contacts = config('Metadata.SP.contacts', []);

        foreach($contacts as $contact)
        {
            $sp->addContactPerson(
                (new ContactPerson())
                    ->setGivenName(isset($contact['givenName']) ? $contact['givenName'] : '')
                    ->setSurName(isset($contact['surName']) ? $contact['surName'] : '')
                    ->setContactType(isset($contact['contactType']) ? $contact['contactType'] : '')
                    ->setCompany(isset($contact['company']) ? $contact['company'] : '')
                    ->setEmailAddress(isset($contact['emailAddress']) ? $contact['emailAddress'] : '')
                    ->setTelephoneNumber(isset($contact['telephoneNumber']) ? $contact['telephoneNumber'] : '')
            );
        }

        $sp->addAssertionConsumerService(
            (new AssertionConsumerService())
                ->setIsDefault(true)
                ->setBinding(config('Metadata.SP.AssertionConsumerService.binding'))
                ->setLocation(sprintf("%s%s", config('Metadata.baseUrl'), config('Metadata.SP.AssertionConsumerService.location')))
        );


        $sp->addSingleLogoutService(
            (new SingleLogoutService())
                ->setBinding(config('Metadata.SP.SLO.binding'))
                ->setLocation(sprintf("%s%s", config('Metadata.baseUrl'), config('Metadata.SP.SLO.location')))
        );


        $keys = config('Metadata.SP.keys', []);

        foreach($keys as $use => $key)
        {
            $sp->addKeyDescriptor(
                (new KeyDescriptor())
                    ->setUse($use)
                    ->setCertificate((new X509Certificate)->setData($key['x509']))
            );
        }

        $entity->addItem($sp);

        $this->entity = $entity;
    }
}