<?php

namespace RAP;

class GmsClient {

    private $locator;

    public function __construct(Locator $locator) {
        $this->locator = $locator;
    }

    public function joinGroups(string $userId1, string $userId2): string {
        if (!isset($this->locator->config->gms)) {
            return $userId1;
        }

        //create cURL connection
        $conn = curl_init($this->locator->config->gms->joinEndpoint);

        //set options
        curl_setopt($conn, CURLOPT_CONNECTTIMEOUT, 30);
        curl_setopt($conn, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($conn, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($conn, CURLOPT_FOLLOWLOCATION, 1);
        // Setting an empty body, otherwise Content-Length will be negative and Spring will answer with 400
        curl_setopt($conn, CURLOPT_POSTFIELDS, " ");
        curl_setopt($conn, CURLOPT_HTTPHEADER, ['Authorization: Bearer '
            . $this->getJoinAccessToken($userId1, $userId2)]);

        //set data to be posted
        curl_setopt($conn, CURLOPT_POST, 1);

        //perform the request
        $response = curl_exec($conn);
        $info = curl_getinfo($conn);

        if ($info['http_code'] === 200) {
            $joinResult = json_decode($response);
            curl_close($conn);
            if (!array_key_exists('mergedId', $joinResult)) {
                throw new ServerErrorException('GMS join response has an invalid payload');
            }
            return $joinResult->mergedId;
        } else {
            //show information regarding the error
            curl_close($conn);
            error_log($response);
            $httpCode = $info['http_code'];
            if ($httpCode === 0) {
                throw new ServerErrorException('GMS service is unreachable');
            }
            throw new ServerErrorException('Error: GMS response code: ' . $httpCode);
        }
    }

    private function getJoinAccessToken(int $userId1, int $userId2): string {

        $gmsId = $this->locator->config->gms->id;

        $accessToken = new AccessTokenData();
        $accessToken->clientId = $gmsId;
        $accessToken->userId = $userId1;
        // shorter expiration
        $accessToken->expirationTime = $accessToken->creationTime + 100;
        $accessToken->scope = ['openid'];

        return $this->locator->getTokenBuilder()->getAccessToken($accessToken, function(& $jwt) use($userId2) {
                    $jwt['alt_sub'] = strval($userId2);
                });
    }

}