<?php

namespace sent\jwt\claim;

use think\Request;

class Factory {
	protected $classMap
	= [
		'aud' => Audience::class,
		'exp' => Expiration::class,
		'iat' => IssuedAt::class,
		'iss' => Issuer::class,
		'jti' => JwtId::class,
		'nbf' => NotBefore::class,
		'sub' => Subject::class,
	];

	protected $ttl;
	protected $claim = [];
	protected $refreshTtl;

	public function __construct(Request $request, $ttl, $refreshTtl) {
		$this->request    = $request;
		$this->ttl        = $ttl;
		$this->refreshTtl = $refreshTtl;
	}

	public function customer($key, $value) {
		$this->claim[$key] = isset($this->classMap[$key])
		? new $this->classMap[$key]($value)
		: new Customer($key, $value);

		return $this;
	}

	public function builder() {
		foreach ($this->classMap as $key => $class) {
			$claim[$key] = new $class(method_exists($this, $key)
				? $this->$key() : '');
		}
		$this->claim = array_merge($this->claim, $claim);

		return $this;
	}

	public function validate($refresh = false) {
		foreach ($this->claim as $key => $claim) {
			if (!$refresh && method_exists($claim, 'validatePayload')) {
				$claim->validatePayload();
			}
			if ($refresh && method_exists($claim, 'validateRefresh')) {
				$claim->validateRefresh($this->refreshTtl);
			}
		}
	}

	public function getClaims() {
		return $this->claim;
	}

	public function aud() {
		return $this->request->url();
	}

	public function exp() {
		return time() + $this->ttl;
	}

	public function iat() {
		return time();
	}

	public function iss() {
		return $this->request->url();
	}

	public function jti() {
		return md5(uniqid() . time() . rand(100000, 9999999));
	}

	public function nbf() {
		return time();
	}
}
