<?php

namespace AuthStack\SAMLServiceProvider\Model;

use LightSaml\Credential\KeyHelper;
use LightSaml\Credential\X509Certificate;
use LightSaml\Model\XmlDSig\SignatureWriter;
use RobRichards\XMLSecLibs\XMLSecurityKey;

class ServiceProvider
{
    /**
     * @return null|string
     */
    public function getEntityId(): ?string
    {
        return config('saml.sp.EntityId');
    }

    /**
     * @return string
     */
    public function getIdPEntityId(): string
    {
        return config('saml.sp.IdentityProvider');
    }

    /**
     * @return string
     */
    public function getBaseUrl(): string
    {
        return config('saml.sp.baseUrl');
    }

    /**
     * @return null|string
     */
    public function getNameIdFormat(): ?string
    {
        return config('saml.sp.nameIdFormat');
    }

    /**
     * @return bool
     */
    public function wantsSignedMessages(): bool
    {
        return config('saml.sp.wantsSignedMessages');
    }

    /**
     * @return bool
     */
    public function wantsSignedAssertions(): bool
    {
        return config('saml.sp.wantsSignedAssertions');
    }

    /**
     * @return bool
     */
    public function wantsEncryptedAssertions(): bool
    {
        return config('saml.sp.wantsEncryptedAssertions');
    }

    /**
     * @return string
     */
    public function getACSPath(): string
    {
        return config('saml.sp.AssertionConsumerService.location');
    }

    /**
     * @return string
     */
    public function getACSUrl(): string
    {
        return sprintf("%s%s", $this->getBaseUrl(), $this->getACSPath());
    }

    /**
     * @return string
     */
    public function getACSBinding(): string
    {
        return config('saml.sp.AssertionConsumerService.binding');
    }

    /**
     * @return string
     */
    public function getLogoutServicePath(): string
    {
        return config('saml.sp.SLO.location');
    }

    /**
     * @return string
     */
    public function getLogoutServiceUrl(): string
    {
        return sprintf("%s%s", $this->getBaseUrl(), $this->getLogoutServicePath());
    }

    /**
     * @return string
     */
    public function getLogoutServiceBinding(): string
    {
        return config('saml.sp.SLO.binding');
    }

    public function validateSignature(): bool
    {
        return config('saml.sp.validate.signature');
    }

    /**
     * @return bool
     */
    public function validateStatus(): bool
    {
        return config('saml.sp.validate.status');
    }

    /**
     * @return bool
     */
    public function validateIssuer(): bool
    {
        return config('saml.sp.validate.issuer');
    }

    /**
     * @return bool
     */
    public function validateDestination(): bool
    {
        return config('saml.sp.validate.destination');
    }

    /**
     * @return bool
     */
    public function validateLifetime(): bool
    {
        return config('saml.sp.validate.lifetime');
    }

    /**
     * @return \DateTime
     */
    public function getUpperDT(): \DateTime
    {
        return new \DateTime($this->getValidationUpperTimeBoundary(), new \DateTimeZone('UTC'));
    }

    /**
     * @return \DateTime
     */
    public function getLowerDT(): \DateTime
    {
        return new \DateTime($this->getValidationLowerTimeBoundary(), new \DateTimeZone('UTC'));
    }

    /**
     * @return string
     */
    public function getValidationUpperTimeBoundary(): string
    {
        return config('saml.sp.validate.upper');
    }

    /**
     * @return string
     */
    public function getValidationLowerTimeBoundary(): string
    {
        return config('saml.sp.validate.lower');
    }

    /**
     * @return array
     */
    public function getSigningKey(): array
    {
        return config('saml.sp.keys.signing', []);
    }

    /**
     * @return SignatureWriter
     */
    public function getSignatureWriter(): SignatureWriter
    {
        $x509 = new X509Certificate();

        $x509->setData($this->getSigningKeyX509Cert());

        $priv = KeyHelper::createPrivateKey(
            $this->getSigningPrivateKey(),
            $this->getSigningPrivateKeyPassphrase(),
            false,
            $this->getSigningDigestAlgorithm()
        );

        return new SignatureWriter($x509, $priv);
    }

    /**
     * @return XMLSecurityKey
     */
    public function getSigningPublicKey(): XMLSecurityKey
    {
        return KeyHelper::createPublicKey(
            (new X509Certificate())->setData($this->getSigningKeyX509Cert())
        );
    }

    /**
     * @return string
     */
    public function getSigningKeyX509Cert(): string
    {
        return config('saml.sp.keys.signing.x509');
    }

    /**
     * @return string
     */
    public function getSigningPrivateKey(): string
    {
        return config('saml.sp.keys.signing.private');
    }

    /**
     * @return null|string
     */
    public function getSigningPrivateKeyPassphrase(): ?string
    {
        return config('saml.sp.keys.signing.passphrase');
    }

    /**
     * @return string
     */
    public function getSigningDigestAlgorithm(): string
    {
        return config('saml.sp.keys.signing.algorithm');
    }

    /**
     * @return array
     */
    public function getDecryptionKey(): array
    {
        return config('saml.sp.keys.encryption', []);
    }

    /**
     * @return XMLSecurityKey
     */
    public function getDecrypter(): XMLSecurityKey
    {
        return KeyHelper::createPrivateKey(
            $this->getDecryptionKeyPrivateKey(),
            $this->getDecryptionKeyPassphrase(),
            false,
            $this->getDecryptionKeyAlgorithm()
        );
    }

    /**
     * @return null|string
     */
    public function getDecryptionKeyPrivateKey(): ?string
    {
        return config('saml.sp.keys.encryption.private');
    }

    /**
     * @return null|string
     */
    public function getDecryptionKeyPassphrase(): ?string
    {
        return config('saml.sp.keys.encryption.passphrase');
    }

    /**
     * @return null|string
     */
    public function getDecryptionKeyAlgorithm(): ?string
    {
        return config('saml.sp.keys.encryption.algorithm');
    }
}