<?php 
namespace OfficeBrain\Bundle\ApiClientBundle\ApiClient;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;


abstract class AbstractApiClient{
	
	/**
	 *
	 * @var Request
	 */
	protected $request;
	
	/**
	 *
	 * @var string
	 */
	protected $accessToken;
	
	/**
	 *
	 * @var string
	 */
	protected $apiBaseUrl;
	
	protected $apiCallType;
	
	protected $apiCallUrl;
	
	protected $callParameters;
	
	protected $result_set;
	
	protected $totalResultFound;
	
	protected $culture;
	
	protected $isError;
	
	protected $errorCode;
	
	protected $errorDescription;
	protected $post;
	protected $trace;
	
	protected $apiVersionToUse;
	
	protected $container;
	
	public abstract function doProcess();
	/**
	 *
	 * @param Request $request
	 * @param string $apiUrl
	 * @param string $accessToken
	 */
	public function __construct(Request $request, $apiUrl, $accessToken, $defaultApiVersion, $availableCallToOverride, Container $container=null){		
		$this->request = $request;
		$this->apiDefaultUrl = $apiUrl;
		$this->apiBaseUrl = $apiUrl;
		$this->accessToken = $accessToken;
		$this->container = $container;
		$this->defaultApiVersion = $defaultApiVersion;
		$this->availableCallToOverride = (array)$availableCallToOverride;
		$this->apiVersionToUse = $this->defaultApiVersion;
		$this->projectSetting = $this->request->get('project_setting');
		$this->projectUserSetting = $this->request->get('project_user_setting')['user_data'];
	}
	
	public function setApiVersionToUse($apiVersion){
		$this->apiVersionToUse = $apiVersion;
	}
	
	public function getApiVersionToUse(){
		return $this->apiVersionToUse;
	}
	
	/**
	 * Set custom API URL
	 * @param string $apiUrl
	 */
	public function setApiUrl($apiUrl){
		$this->apiUrl = $apiUrl;
	}
	
	public function init($apiCallType){
		self::ResetAll();
		$this->apiCallType = trim($apiCallType);
		
		if(array_key_exists($this->apiCallType, $this->availableCallToOverride)){
			$this->setApiVersionToUse($this->availableCallToOverride[$this->apiCallType]);
		} else {
			$this->setApiVersionToUse($this->defaultApiVersion);
		}
		
		$this->apiBaseUrl = str_replace('__VERSION__',$this->getApiVersionToUse(), $this->apiDefaultUrl);
	}
	
	public function setCulture($culture){
		$this->culture = $culture;
	}
	
  public function getCulture(){
    return $this->culture ;
  }
  
  public function setResultSet($ResultSet){
    $this->result_set = $ResultSet;
  }
  
	public function isSuccess(){
		return !$this->isError;
	}
	
	public function setError($errorCode, $errorDescription){
		$this->isError = true;
		$this->errorCode = $errorCode;
		$this->errorDescription = $errorDescription;
	}
	
	private function ResetAll(){
		$this->isError = false;
		$this->errorCode = '';
		$this->errorDescription = '';
		$this->callParameters = array();
		$this->result_set = array();
		$this->totalResultFound = '';
		$this->culture = '';
		$this->post = false;
		$this->trace = false;
	}
	
	public function setPostMethodTrue(){
		$this->post = true;
	}
	
	public function setTraceMethodTrue(){
		$this->trace = true;
	}
	
	public function getErorCode(){
		return $this->errorCode;
	}
	
	public function getErorDescription(){
		return $this->errorDescription;
	}
	
	public function getCallParameters(){
		return $this->callParameters;
	}
	
	public function setCallParameters($callParameters){
		
		$this->callParameters = $callParameters;
		$this->callParameters['project_id'] = $this->projectSetting['project_id'];
		$this->callParameters['ob_id'] =  ($this->projectUserSetting) ? str_replace('ob', '', strtolower($this->projectUserSetting->getObCustomerId())) : '';
	}
	
	public function getTotalResultFound(){
		return $this->totalResultFound;
	}
	
	public function getResultArray(){
		return $this->result_set;
	}
  
  public function updateCallParameters($options=array()){
      $this->callParameters=array_merge($this->callParameters,$options);
  }
	
	protected function callApi(){
		$ch = curl_init();
		if($this->post){
			curl_setopt($ch, CURLOPT_POST,true);
			@curl_setopt($ch, CURLOPT_POSTFIELDS,$this->callParameters);
			curl_setopt($ch, CURLOPT_URL, $this->apiBaseUrl.$this->apiCallUrl);
		}else{
			$this->prepareApiUrlParameter();
			curl_setopt($ch, CURLOPT_URL, $this->apiCallUrl);
		}
		
		
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_TIMEOUT, 4);
		curl_setopt($ch, CURLOPT_TIMEOUT, 1000);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,false);
						
		
		$this->result_set = curl_exec($ch);
		
		
		if($this->trace){
		    echo "Call Url: ", $this->apiCallUrl;
		    print_r($this->result_set);
		    die;
			//$this->trace = false;
		}
		
		if (curl_errno($ch)) {
			$this->setError('MAKE_CALL_ERROR->' . curl_errno($ch), curl_error($ch));
		}
		else {
			$return_code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
			
			if ($return_code == 404) {
				$this->setError('MAKE_CALL_ERROR', '404_Not_Found');
			}
			else {
				$debug_result = $this->result_set;				
				$this->result_set = json_decode($this->result_set, true);
				
				if (!is_array($this->result_set)) {
					/*if(__ENV__=="dev" && $this->trace){
						echo "<pre>";
						print_r($debug_result);
						echo "<pre>";
						exit;
					}	*/				
					$this->setError('MAKE_CALL_ERROR', 'NO_DATA_FOUND');
				}
				else if (array_key_exists('error', $this->result_set)) {
					$this->setError($this->result_set['error'], $this->result_set['error_description']);
				}else if (array_key_exists('error_message', $this->result_set)) {
					$this->setError('ERROR', $this->result_set['error_message']);					
				}
				else {
					$this->totalResultFound = count($this->result_set);
				}
			}
		}	
		curl_close($ch);
	}
	
	protected function uploadFileAndCallApi(){
		$ch = curl_init();
		
		if(__PHP_VERSION__>=54){
			$cfile = curl_file_create($this->callParameters['file']);
			$this->callParameters['file'] = $cfile;
		}
		
		curl_setopt($ch, CURLOPT_URL, $this->apiBaseUrl.$this->apiCallUrl);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);		
		//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,false);
		curl_setopt($ch, CURLOPT_POST,true);
		//curl_setopt($ch, CURLOPT_HTTPHEADER,array("Content-Type:multipart/form-data"));
		curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
		@curl_setopt($ch, CURLOPT_POSTFIELDS,$this->callParameters);
		
		
		$this->result_set = curl_exec($ch);
		
		if($_SERVER['REMOTE_ADDR']=='127.0.0.1' && $this->trace){
			print_r($this->result_set);
		}
		
		//print_r($this->result_set);
		
		if (curl_errno($ch)) {
			$this->setError('MAKE_CALL_ERROR->' . curl_errno($ch), curl_error($ch));
		}
		else {
			$return_code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
			if ($return_code == 404) {
				$this->setError('MAKE_CALL_ERROR', '404 Not Found');
			}
			else {
				$this->result_set = json_decode($this->result_set, true);
				if (!is_array($this->result_set)) {
					$this->setError('MAKE_CALL_ERROR', 'NO_DATA_FOUND');
				}
				else if (array_key_exists('error', $this->result_set)) {
					$this->setError($this->result_set['error'], $this->result_set['errorDescription']);
				}
				else {
					$this->totalResultFound = count($this->result_set);
				}
			}
		}
		curl_close($ch);
	}
	
	private function prepareApiUrlParameter(){	
		$apiParameterArray = array();
		foreach ($this->callParameters as $parameterName=>$parameterValue) {
			if(is_array($parameterValue)){
				$parameterValue = json_encode($parameterValue);
			}
				$apiParameterArray[] = $parameterName.'='.urlencode($parameterValue);
		}
		
		$apiParameterArray[] = 'culture='.$this->culture;
		$apiParameterArray[] = 'accessToken='.$this->accessToken;
	
		$this->apiCallUrl = $this->apiBaseUrl.$this->apiCallUrl.'?'.implode('&', $apiParameterArray);
		
		unset($apiParameterArray);
	}
	
	public function getApiCallUrl(){
		return $this->apiCallUrl;
	}
	
	public function getResultSet(){
		return $this->result_set;
	}
	
	public function getExtraInfo($key){
		if(array_key_exists($key,$this->result_set)){
			return $this->result_set[$key];
		}
		return false;
	}
}