<?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\Requests;


use LightSaml\Credential\KeyHelper;
use LightSaml\Model\Assertion\Issuer;
use LightSaml\Credential\X509Certificate;
use LightSaml\Model\Protocol\AuthnRequest;
use LightSaml\Model\Protocol\LogoutRequest;
use LightSaml\Model\XmlDSig\SignatureWriter;
use LightSaml\Model\Context\SerializationContext;

/**
 * Class AbstractRequest
 * @package AuthStack\SP\Requests
 */
abstract class AbstractRequest
{
    protected $idp;
    protected $request_id;

    public function __construct($idp)
    {
        $this->idp = sha1($idp);

        $this->create();
    }


    abstract protected function create();

    /**
     * @return AuthnRequest|LogoutRequest
     */
    abstract public function getRequest();


    /**
     * @return string
     */
    public function getRequestId()
    {
        return $this->request_id;
    }

    /**
     * @param bool|false $base64
     *
     * @return string
     */
    public function toXml($base64 = false)
    {
        $ctx = new SerializationContext();

        $authn = $this->getRequest();

        $authn->serialize($ctx->getDocument(), $ctx);

        $xml = $ctx->getDocument()->saveXML();

        if($base64)
        {
            return base64_encode($xml);
        }

        return $xml;
    }

    /**
     * @return Issuer
     */
    protected function getIssuer()
    {
        return new Issuer(\Buckhill\config('AuthStack.SP.entityId'));
    }


    /**
     * @return bool
     */
    protected function IdPWantsSignedRequests()
    {
        return \Buckhill\config(sprintf('AuthStack.IdP.%s.wantsSignedRequests', $this->idp), false);
    }


    /**
     * @return SignatureWriter
     */
    protected function getSignature()
    {
        $x509 = new X509Certificate();

        $cert = \Buckhill\config('AuthStack.SP.keys.signing.x509');
        $private = \Buckhill\config('AuthStack.SP.keys.signing.private');
        $passphrase = \Buckhill\config('AuthStack.SP.keys.signing.passphrase', '');


        $x509->setData($cert);

        $priv = KeyHelper::createPrivateKey(
            $private,
            $passphrase,
            false
        );

        $writer = new SignatureWriter(
            $x509,
            $priv
        );

        return $writer;
    }




    /**
     *
     */
    protected function initiateWithPOST()
    {
        $encodedXml = $this->toXml(true);
        $destination = $this->getRequest()->getDestination();

        $html = <<<EOF
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>SAML Authentication Request</title>
</head>
<body onload="document.getElementsByTagName('input')[0].click();">

<noscript>
    <p><strong>Note:</strong> Since your browser does not support JavaScript, you must press the button below once to proceed.</p>
</noscript>

<form method="post" action="$destination">
    <input type="submit" style="display:none;" />

    <input type="hidden" name="SAMLRequest" value="$encodedXml" />

    <noscript>
        <input type="submit" value="Submit" />
    </noscript>

</form>
</body>
</html>
EOF;

        echo $html;
    }


    /**
     *
     */
    protected function initiateWithGET()
    {
        $xml = $this->toXml();

        $zipped = gzdeflate($xml);

        $encoded = base64_encode($zipped);

        $destination = $this->getRequest()->getDestination();

        header(sprintf("Location: %s?SAMLRequest=%s", $destination, $encoded));
    }
}