<?php
namespace App\Controller;


use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;

use OAT\Library\Lti1p3Core\Message\Launch\Builder\PlatformOriginatingLaunchBuilder;
use OAT\Library\Lti1p3Core\Message\LtiMessageInterface;
use OAT\Library\Lti1p3Core\Message\Payload\Claim\ContextClaim;
use OAT\Library\Lti1p3Core\Registration\RegistrationRepositoryInterface;
use OAT\Library\Lti1p3Core\Resource\LtiResourceLink\LtiResourceLink;
use OAT\Library\Lti1p3Core\Registration\Registration;
use OAT\Library\Lti1p3Core\Platform\Platform;
use OAT\Library\Lti1p3Core\Tool\Tool;
use OAT\Library\Lti1p3Core\Security\Key\KeyChain;
use OAT\Library\Lti1p3Core\Security\Key\Key;
use OAT\Library\Lti1p3Core\Message\Launch\Builder\LtiResourceLinkLaunchRequestBuilder;
use OAT\Library\Lti1p3Core\Security\User\UserAuthenticatorInterface;
use OAT\Library\Lti1p3Core\Security\Oidc\OidcAuthenticator;
use OAT\Library\Lti1p3Core\Security\Oidc\OidcInitiator;
use OAT\Library\Lti1p3Core\Security\User;
use OAT\Library\Lti1p3Core\User\UserIdentity;

use Nyholm\Psr7\Factory\Psr17Factory;
use Psr\Http\Message\ServerRequestInterface;

class DefaultController extends AbstractController
{
    private $repo;
    private $builder;
    private $userAuthenticator;

    public function __construct(RegistrationRepositoryInterface $repo, LtiResourceLinkLaunchRequestBuilder $builder)
    {
        $this->repo = $repo;
        $this->builder = $builder;
    }

    private function createServerRequest(string $method, string $uri, array $params = [], array $headers = []): ServerRequestInterface 
    {
        $serverRequest =  (new Psr17Factory())->createServerRequest($method, $uri);

        foreach ($headers as $headerName => $headerValue) {
            $serverRequest = $serverRequest->withAddedHeader($headerName, $headerValue);
        }

        $method = strtoupper($method);

        if ($method === 'GET') {
            return $serverRequest->withQueryParams($params);
        }

        if ($method === 'POST') {
            return $serverRequest->withParsedBody($params);
        }

        return $serverRequest;
    }

    /**
     * @Route("/default", name="default_list")
     */   
    public function list()
    {
        /*** CREATE THE MESSAGE ***/

        // Create a builder instance
        $builder = new PlatformOriginatingLaunchBuilder();

        // Get related registration of the launch
        /** @var RegistrationRepositoryInterface $registrationRepository */

        //$projectRoot = $this->getParameter('kernel.project_dir');

        //create registration
        /*$registrations[] = new Registration(
            'local',  // [required] identifier
            'common_client_id_value',  // [required] client id
            new Platform('localPlatform', 'Click Learner Portal', 'http://127.0.0.1:8000/platform', 
                'http://devkit-lti1p3-master-tool/lti1p3/oidc/authentication', 
                'http://127.0.0.1:8000/lti1p3/auth/platformKey/token'),    // [required] (PlatformInterface) platform 
            new Tool('localTool', 'Local tool', 'http://127.0.0.1:8000/tool', 'http://devkit-lti1p3-master-tool/lti1p3/oidc/initiation', null, null),                     // [required] (ToolInterface) tool 
            array("deploymentId1", "deploymentId2"),  // [required] (array) deployments ids 
            new KeyChain("platformKey", "platformSet", 
                new Key("file://" . $projectRoot . "/config/secrets/dev/public.key"), 
                new Key("file://" . $projectRoot . "/config/secrets/dev/private.key"), null),         // [optional] (KeyChainInterface) key chain of the platform 
            //$toolKeyChain,             // [optional] (KeyChainInterface) key chain of the tool 
            //$platformJwksUrl,          // [optional] JWKS url of the platform
            //$toolJwksUrl,              // [optional] JWKS url of the tool
        );
       
        $registrationArray = !empty($registrations) ? $registrations : [$this->createTestRegistration()];

        $registrationRepository = new RegistrationRepository($registrationArray);
        $registration = $registrationRepository->find('local');*/

        $registration = $this->repo->find('local');

        $ltiResourceLink = new LtiResourceLink(
            'resourceLinkIdentifier', //needs to be unique
            [
                'url' => 'http://127.0.0.1:8001/tool/launch',
                'title' => 'LTI Resource Link'
            ]
        );

        $message = $this->builder->buildLtiResourceLinkLaunchRequest(
            $ltiResourceLink,
            $registration,
            'loginHint'
        );

        // 1 + 2
        $oidcInitiator = new OidcInitiator($this->repo);
        $oidcInitiationResult = $oidcInitiator->initiate($this->createServerRequest('GET', $message->toUrl()));
        dump($oidcInitiationResult);
      
        // 3 + 4
        // Perform the login authentication (delegating to the $userAuthenticator with the hint 'loginHint') 
        $userAuthenticator = new UserAuthenticator(true, true); // TESTING ONLY, 2nd param needs to be false
        $oidcAuthenticator = new OidcAuthenticator($this->repo, $userAuthenticator);
        //dump($oidcAuthenticator);
        $oidcAuthenticationResult = $oidcAuthenticator->authenticate($this->createServerRequest('GET', $oidcInitiationResult->toUrl()));
        
        dump($oidcAuthenticationResult);
        //return new Response('test');
        
        // Auto redirection to the tool via the user's browser
        return new Response($oidcAuthenticationResult->toHtmlRedirectForm());
        //return new Response($message->toHtmlRedirectForm('launch LTI Resource Link'));
        
        // Build a launch message
        /*$message = $builder->buildPlatformOriginatingLaunch(
            $registration,                                               // related registration
            LtiMessageInterface::LTI_MESSAGE_TYPE_RESOURCE_LINK_REQUEST, // message type of the launch, as an example: 'LtiDeepLinkingResponse'
            'https://testrunner-ignite.prod.gcp-eu.taocloud.org/api/v1/auth/launch-lti-1p3/',                                    // target link uri of the launch (final destination after OIDC flow)
            'loginHint',                                                 // login hint that will be used afterwards by the platform to perform authentication
            null,                                                        // will use the registration default deployment id, but you can pass a specific one
            [
                'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner' // role
            ],
            [
                'myCustomClaim' => 'myCustomValue',    // custom claim
                new ContextClaim('contextIdentifier')  // LTI claim representing the context of the launch 
            ]
        );*/

        //dump($message);

        /*** LAUNCH THE MESSAGE ***/

        /** @var LtiMessageInterface $message */

        // Main message properties you can use as you want to offer the launch to the platform users
        echo $message->getUrl();               // url of the launch
        //echo $message->getParameters()->all(); // array of parameters of the launch

        // Or use those helpers methods to ease the launch interactions
        echo $message->toUrl();                // url with launch parameters as query parameters
        echo $message->toHtmlLink('click me'); // HTML link, where href is the output url
        echo $message->toHtmlRedirectForm();   // HTML hidden form, with possibility of auto redirection


        /*** LAUNCHING AN LTI RESOURCE LINK ***/

        $ltiResourceLink = new LtiResourceLink(
            'resourceLinkIdentifier',
            [
                'url' => 'http://tool.com/resource',
                'title' => 'Some title'
            ]
        );

        // Create a builder instance
        $builder = new LtiResourceLinkLaunchRequestBuilder();

        // Get related registration of the launch
        /** @var RegistrationRepositoryInterface $registrationRepository */
        $registration = $registrationRepository->find('local');

        // Build a launch message
        $message = $builder->buildLtiResourceLinkLaunchRequest(
            $ltiResourceLink, // LTI resource link to launch
            $registration,    // related registration
            'loginHint',      // hint about the user login process that will be done on a later step
            null,             // will use the registration default deployment id, but you can pass a specific one
            [
                'http://purl.imsglobal.org/vocab/lis/v2/membership#Learner' // role
            ], 
            [
                new ContextClaim('contextId'),     // LTI claim representing the context 
                'myCustomClaim' => 'myCustomValue' // custom claim
            ]
        );

        /** @var LtiMessageInterface $message */

        // Main message properties you can use as you want to offer the launch to the platform users
        echo $message->getUrl();               // url of the launch
        //echo $message->getParameters()->all(); // array of parameters of the launch

        // Or use those helpers methods to ease the launch interactions
        echo $message->toUrl();                // url with launch parameters as query parameters
        echo $message->toHtmlLink('click me'); // HTML link, where href is the output url
        echo $message->toHtmlRedirectForm();   // HTML hidden form, with possibility of auto redirection
    
        return new Response($message->toHtmlLink('launch LTI Resource Link'));
    }

}

?>