<?php

namespace App\CurrencyExchange;

class System_NbsRS extends SystemAbstract
{

	/**
	 * The reference currency.
	 * @var String
	 */
	protected $referenceCurrency='RSD';

	/**
	 * The system address.
	 * @var String
	 */
	protected $systemAddress='https://webservices.nbs.rs/CommunicationOfficeService1_0/CurrentExchangeRateService.asmx?WSDL';

	/**
	 * The system credentials - licenseNo
	 * @var String
	 */
	protected $auth_licenseNo = null;

	/**
	 * The system credentials - username
	 * @var String
	 */
	protected $auth_username = null;

	/**
	 * The system credentials - password
	 * @var String
	 */
	protected $auth_password = null;

	/**
	 * The field from the response that will be used to get the rate value; can be: BuyingRate,MiddleRate,SellingRate.
	 * @var String
	 */
	protected $rateUsed = null;

	/**
	 * Exchange rate list type; can be: 1, 2 ir 3 (for updates check GetExchangeRateListType method from service)
	 * 1 seems to fill in BuyingRate, SellingRate
	 * 3 seems to fill in MiddleRate
	 * 2 seems to fill in all 3 tags, but only for few currencies
	 * @var Int
	 */
	protected $exchangeRateListTypeID=null;

	public function __construct($date='')
	{
		$CFG = \Engine\Loader_Cfg::getInstance()->getGlobal();
		$this->auth_licenseNo = $CFG['currencies']['System']['NbsRS']['auth_licenseNo'];
		$this->auth_username = 	$CFG['currencies']['System']['NbsRS']['auth_username'];
		$this->auth_password = 	$CFG['currencies']['System']['NbsRS']['auth_password'];

		switch ($CFG['currencies']['System']['NbsRS']['rateLoaded']) {
			case 'selling':
				$this->rateUsed = 'SellingRate';
				$this->exchangeRateListTypeID = 1;
			break;

			case 'middle':
				$this->rateUsed = 'MiddleRate';
				$this->exchangeRateListTypeID = 3;
			break;

			default:
				throw new \Exception(sprintf("[%s] Unknown loaded rate defined: %s", __METHOD__, $CFG['currencies']['System']['NbsRS']['rateLoaded']));
		}

		parent::__construct($date);
	}

	/**
	 * Gets the exchange rates for this system.
	 * @return Array
	 */
	public function getRates()
	{
		// RUN WEB SERVICE REQUEST ////////////////////////////////////////////////////////////////
		try {
			// connect through a proxy
			if ($this->proxyHost) {
				$client = new \soapclient($this->systemAddress,
					[
						'trace'				=> true,
						'exceptions' 		=> true,
						'encoding'			=>'utf-8',
						'connection_timeout'=> 15,
						'proxy_host'     	=> $this->proxyHost,
	                    'proxy_port'     	=> $this->proxyPort,
	                    'proxy_login'    	=> $this->proxyUser,
	                    'proxy_password' 	=> $this->proxyPass,
					]
				);
			}
			// connect directly
			else {
				$client = new \soapclient($this->systemAddress,
					[
						'trace'				=> true,
						'exceptions' 		=> true,
						'encoding'			=>'utf-8',
						'connection_timeout'=> 15
					]
				);
			}

			// set auth headers http://communicationoffice.nbs.rs
			$ns="http://communicationoffice.nbs.rs";
			// set auth data
			$header = new \SoapHeader($ns, "AuthenticationHeader", ['UserName'=>$this->auth_username, 'Password'=>$this->auth_password, 'LicenceID'=>$this->auth_licenseNo]);
			$client->__setSoapHeaders($header);

			// call method and get echange rates
			$response=$client->GetCurrentExchangeRate( ['exchangeRateListTypeID'=>$this->exchangeRateListTypeID]);

		}
		catch (\SoapFault $fault) {
			throw new Exception("An error occured during webservice request: ".$fault->faultstring);
		}

		// GET THE RESPONSE CONTENT ///////////////////////////////////////////////////////////////
		if (!$response->GetCurrentExchangeRateResult->any) throw new Exception("The server content is not valid.");
		$fileContent=@simplexml_load_string($response->GetCurrentExchangeRateResult->any);
		if (!$fileContent) throw new Exception('The external system webservice reply was not a well formed XML.');

		// PARSE RESPONSE CONTENT /////////////////////////////////////////////////////////////////
		$result=[];
		$items=$fileContent->ExchangeRateDataSet[0];
		$rateUsed=$this->rateUsed;
		if ($items) {
			foreach ($items as $thisCurr) {
				// get raw data
				$currCode=(String)$thisCurr->CurrencyCodeAlfaChar; // the currency code
				$units=(float)$thisCurr->Unit; // the number of units
				$rate=(float)$thisCurr->{$rateUsed}; // the rate for given number of units
				// set currency exchange rates
				if ($units>0) $result[$currCode]=$rate/$units;
			}
		}

		return $result;

	}

}

