<?php

use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

Class Bt50ApiClient {
	private $client = null;
	private $apiKey = null;
	const API_URL = 'https://www.billtrack50.com/BT50Api/2.0/json/';

	public function __construct($key) {
		$this->apiKey = $key;
		$this->client = new Client([
			'base_uri' => self::API_URL,
			'headers' => [
				'Authorization' => 'apikey ' . $key,
				'Content-Type' => 'application/json',
				'Accept' => 'application/json'
			]
		]);
	}

	public function connectionValid() {
		try {
			$response = $this->client->get('Legislators?LegislatorName=zzzzz&StateCodes=ia');
		} catch (RequestException $e) {
			return false;
		}
		return round($response->getStatusCode() / 200) == 1;
	}

	public function getCurrentSessionByScorecard($scorecardId) {
		$scorecard = $this->scorecard($scorecardId);
		if (!$scorecard) { return; }
		$sessionsResponse = $this->sessions($scorecard['StateCode']);
		//  Scorecards are not limited to sessions. so we can:
		//   1) score by total presence
		//   2) create a way to associate a session with a scorecard
		//   3) hardcode blended data
		$currentSession;
		foreach ($sessionsResponse['Sessions'] as $session) {
			if ($session['CurrentSession']) {
				return $session['SessionID'];
			}
		}
		if (sizeOf($sessionsResponse['Sessions'] > 0)) {
			usort($sessionsResponse['Sessions'], function($a, $b) {
				return ($a['SessionID'] < $b['SessionID']) ? -1 : 1;
			});
			$highestIdSession = end($sessionsResponse['Sessions']);
			return $highestIdSession['SessionID'];
		}

		return;
	}

	public function scorecard($scorecardId) {
		$scorecards = $this->request('Scorecards');
		foreach ($scorecards['Scorecards'] as $scorecard) {
			if (((int)$scorecard['ScorecardID']) == $scorecardId) {
				return $scorecard;
			}
		}
		return;
	}

	public function scorecards() {
		return $this->request('Scorecards');
	}

	public function bills($scorecard_id) {
		$url = 'Scorecards/' . $scorecard_id . '/bills';
		return $this->request($url);
	}

	public function sessions($state_code) {
		$url = 'Sessions/' . $state_code;
		return $this->request($url);
	}

	public function presence($sessionId, $legislatorId = false) {
		if (!$sessionId && !$legislatorId) {
			error_log('At minimum, one of sessionId or legislatorId required');
			return;
		}
		$queryParams = array();
		if ($sessionId) {
			$queryParams['SessionID'] = $sessionId;
		}
		if ($legislatorId) {
			$queryParams['LegislatorID'] = $legislatorId;
		}
		$queryString = http_build_query($queryParams);

		$url = 'Legislators/VotePresence?' . $queryString;
		return $this->request($url);
	}

	public function scorecardLegislatorList($scorecard_id) {
		$url = 'Scorecards/' . $scorecard_id . '/Legislators';
		return $this->request($url);
	}

	public function scorecardLegislatorDetail($args) {
		$scorecard_id = get_option('score_id');
		$url = 'Scorecards/' . $scorecard_id . '/Legislators/'. $args['legislatorId'] . '/votes';
		return $this->request($url);
	}

	private function request($endpoint) {
		try {
			// TODO: do not include api key in transient, instead use a shortened hash
			$transient_key = self::API_URL . $endpoint . $this->apiKey;
			$cachedResponse = get_transient( $transient_key );
			if ($cachedResponse !== false) { return $cachedResponse; }
			$response = $this->client->get($endpoint);
			$result = json_decode((string)$response->getBody(), true);
			set_transient( $transient_key, $result, MINUTE_IN_SECONDS * 30);
			return $result;
		} catch (RequestException $e) {
			$response = $e->getResponse();
			$errorBody = json_decode($response->getBody(), true);
			return new WP_Error(
				'bt50scorecard-apierror',
				$errorBody['ErrorMessage'],
				array( 'status' => 500 )
			);
		}
	}

}
