<?php
namespace App\Authentication\Tokenizer;

use Exception;
use Firebase\JWT\ExpiredException;
use Firebase\JWT\JWT as Token;

/**
 * Class AbstractTokenizer
 * @package App\Authentication\Tokenizer
 */
abstract class AbstractTokenizer implements TokenizerInterface
{
    /**
     * @var string Secret key.
     */
    protected $key;

    /**
     * @var string Signing algorithm. Supported algorithms are 'HS256', 'HS384', 'HS512' and 'RS256'.
     */
    protected $algorithm;

    /**
     * @var int Time to expiration in seconds.
     */
    protected $expiration;

    /**
     * Constructor.
     *
     * @param string $key Secret key.
     * @param int $expiration Time to expiration in seconds.
     * @param string $algorithm Signing algorithm. Supported algorithms are 'HS256', 'HS384', 'HS512' and 'RS256'.
     *
     * @throws Exception
     */
    public function __construct(string $key, $expiration = 3600, string $algorithm = 'HS256')
    {
        if (empty($key)) {
            throw new Exception('Secret key for Tokenizer can\'t be empty.');
        }

        $this->key = $key;
        $this->algorithm = $algorithm;
        $this->expiration = $expiration;
    }

    /**
     * @inheritdoc
     */
    public function encode(array $data): string
    {
        $now = time();

        $body = [
            'iat' => $now,
            'exp' => $now + $this->expiration,
            'data' => $data,
        ];

        return Token::encode($body, $this->key, $this->algorithm);
    }

    /**
     * @inheritdoc
     */
    public function decode(string $encoded)
    {
        $token = null;

        try {
            $token = Token::decode($encoded, $this->key, [$this->algorithm]);
        } catch (ExpiredException $e) {
            throw $e;
//        } catch (Exception $e) {
//            // @todo catch different exceptions
//            return $token;
        }

        return $token;
    }
}