<?php
namespace OfficeBrain\Bundle\ApiClientBundle\ApiClient;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;


abstract class AbstractSoapApiClient{
    /**
     * 
     * @var unknown
     */
    protected $soapBaseUrl;
    
    /**
     * 
     * @var unknown
     */
    protected $soapOptions;

    /**
    * 
    * @var unknown
    */
    protected $result_set;
        
    /**
     * 
     * @var string
     */
    protected $accessToken;

    /**
     * 
     * @var string
     */
    protected $soapParameter;

    /**
     * 
     * @var unknown
     */
    protected $soapFunction;

    /**
     * 
     * @var unknown
     */
    protected $soapUrl;

    /**
     * 
     * @var unknown
     */
    protected $isError;
    
    /**
     * 
     * @var unknown
     */
    protected $apiCallType;
    /**
     * 
     * @var unknown
     */
    protected $errorDescription;
    
    /**
     * 
     * @var unknown
     */
    protected $container;
    
    /**
     * 
     * @var unknown
     */
    protected $request;
    
    /**
     * @var unknown
     */
    protected $callParameters;
    
    /**
     * @var unknown
     */
    protected $responseTag;
    
    /**
     * @var unknown
     */
    protected $requestSoap;
    
    /**
     * 
     * @param Request $request
     * @param string $apiUrl
     * @param string $accessToken
     */
    public function __construct($service_container, Request $request) {

        $this->container = $service_container;        
        $this->soapBaseUrl = '';
        $this->request = $request;
        $this->soapParameter = null;
        $this->soapFunction = null;
        $this->soapUrl = null;
        $this->isError = null;
        $this->errorCode = null;
        $this->errorDescription = null;
        $this->soapOptions = array("soap_version" => SOAP_1_1,"trace" => 1,'cache_wsdl' => 1);
        $this->apiCallType;
        $this->responseTag = null;
        $this->callParameters = array();
    }

    public function __destruct() {
        unset($this->container);
        unset($this->request);
        unset($this->soapParameter);        
        unset($this->soapFunction);
        unset($this->soapUrl);
        unset($this->isError);
        unset($this->errorCode);
        unset($this->errorDescription);
        unset($this->soapOptions);
        unset($this->apiCallType);
        unset($this->soapBaseUrl);
        unset($this->callParameters);
        unset($this->responseTag);
    }

    public function init($apiCallType) {
        $this->isError = false;
        $this->apiCallType = trim($apiCallType);
    }
	
    public function setSoapBaseUrl($soapURL){
    	$this->soapBaseUrl = $this->container->getParameter($soapURL);
    }
    
    public function setError($errorCode, $errorDescription)
    {
        $this->isError = true;
        $this->errorCode = $errorCode;
        $this->errorDescription = $errorDescription;
    }
    public function getSoapParameter($name,$soap,$method, $action)
    {        
        $soapMethods = $this->container->getParameter($name);
        return $soapMethods[$soap][$method][$action];
    }
    
    public function isSuccess(){
		return !$this->isError;
	}
    public function getErorCode()
    {        
            return $this->errorCode;
    }
    public function getErorDescription()
    {
            return $this->errorDescription;
    }
    public function getTotalResultFound()
    {
            return $this->totalResultFound;
    }
    public function getResultArray()
    {
            return $this->result_set;
    }    
    public function getCallParameters()
    {
        return $this->callParameters;
    }
    public function setCallParameters($callParameters){
            $this->callParameters = $callParameters;
    }
    
    public function getResponseTag()
    {
        return $this->responseTag;
    }
    public function setResponseTag($responseTag){
            $this->responseTag = $responseTag;
    }
    public function getRequestSoap()
    {
        return $this->requestSoap;
    }
    
     public function getResponseSoap()
    {
        return $this->responseSoap;
    }
    public function setResponseSoap($responseTag){
            $this->responseSoap = $responseTag;
    }
    
    /* End service */

    public abstract function doProcess();
    
    public function generateResponseArrayFromXML1($data)
    {
        $deXml = simplexml_load_string($data);
        $deJson = json_encode($deXml);
       
        return json_decode($deJson,TRUE);
    }
    protected function callApi() {
        try {
            $client = new \SoapClient($this->soapUrl, $this->soapOptions);
            $client->__soapCall($this->soapFunction, array($this->soapParameter));
            $this->requestSoap = $client->__getLastRequest();
            $this->result_set =  $client->__getLastResponse();
            $this->setResponseSoap($client->__getLastRequest());
        } catch (Exception $client) {
            $this->setError('error', $client->getMessage());
        }
    }

    public function simpleXmlToArray($xmlstring)
    {
        $doc = new \DOMDocument();
        $doc->loadXML($xmlstring);
        return $this->domnode_to_array($doc->documentElement);       
    }

    public function getInnerArrayValue($arrayKey,$array)
    {
       $response = array();
        foreach($array as $key=>$value)
        {           
            if($arrayKey == $key)
            {
                return $array[$key];
            }
            else
            {           
                if(is_array($value))
                {
                    $response = $this->getInnerArrayValue($arrayKey,$value);
                }
            }            
        }        
       return $response;
    }
    

    
    public function generateResponseArrayFromXML($xmlObject)
    {
        $arrayResponse = array();
         $doc = new \DOMDocument();
            $doc->loadXML($xmlObject);
            $books = $doc->getElementsByTagName($this->getResponseTag());
            
            foreach ($books as $book) {
                 $values = $book->getElementsByTagName("*");
                    foreach($values as $node) {
                        $arrayResponse[$node->nodeName] = $node->nodeValue;                     
                    }
                
            }
            return $arrayResponse;
    }
    public function generateArrayFromXML($xmlObject)
    {
        $arrayResponse = array();
         $doc = new \DOMDocument();
            $doc->loadXML($xmlObject);
            $books = $doc->getElementsByTagName($this->getResponseTag());
            
            foreach ($books as $book) {
                 $values = $book->getElementsByTagName("*");
                    foreach($values as $node) {
                        $arrayResponse[$node->nodeName] = $node->nodeValue;                     
                    }
                
            }
            return  $this->domnode_to_array($doc->documentElement);
    }
    public function domnode_to_array($node) {
        $output = array();
        switch ($node->nodeType) {
            case XML_CDATA_SECTION_NODE:
            case XML_TEXT_NODE:
                $output = trim($node->textContent);
                break;
            case XML_ELEMENT_NODE:
                for ($i = 0, $m = $node->childNodes->length; $i < $m; $i++) {
                    $child = $node->childNodes->item($i);
                    $v = $this->domnode_to_array($child);
                    if (isset($child->tagName)) {
                        $t = $child->tagName;
                        if (!isset($output[$t])) {
                            $output[$t] = array();
                        }
                        $output[$t][] = $v;
                    } elseif ($v) {
                        $output = (string) $v;
                    }
                }
                if (is_array($output)) {
                    if ($node->attributes->length) {
                        $a = array();
                        foreach ($node->attributes as $attrName => $attrNode) {
                            $a[$attrName] = (string) $attrNode->value;
                        }
                        $output['@attributes'] = $a;
                    }
                    foreach ($output as $t => $v) {
                        if (is_array($v) && count($v) == 1 && $t != '@attributes') {
                            $output[$t] = $v[0];
                        }
                    }
                }
                break;
        }
        return $output;
    }

    
    public function xml2array($contents, $get_attributes=1, $priority = 'tag') {
    if(!$contents) return array();

    if(!function_exists('xml_parser_create')) {
        //print "'xml_parser_create()' function not found!";
        return array();
    }

    //Get the XML parser of PHP - PHP must have this module for the parser to work
    $parser = xml_parser_create('');
    xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); # http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss
    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
    xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
    xml_parse_into_struct($parser, trim($contents), $xml_values);
    xml_parser_free($parser);

    if(!$xml_values) return;//Hmm...

    //Initializations
    $xml_array = array();
    $parents = array();
    $opened_tags = array();
    $arr = array();

    $current = &$xml_array; //Refference

    //Go through the tags.
    $repeated_tag_index = array();//Multiple tags with same name will be turned into an array
    foreach($xml_values as $data) {
        unset($attributes,$value);//Remove existing values, or there will be trouble

        //This command will extract these variables into the foreach scope
        // tag(string), type(string), level(int), attributes(array).
        extract($data);//We could use the array by itself, but this cooler.

        $result = array();
        $attributes_data = array();
        
        if(isset($value)) {
            if($priority == 'tag') $result = $value;
            else $result['value'] = $value; //Put the value in a assoc array if we are in the 'Attribute' mode
        }

        //Set the attributes too.
        if(isset($attributes) and $get_attributes) {
            foreach($attributes as $attr => $val) {
                if($priority == 'tag') $attributes_data[$attr] = $val;
                else $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
            }
        }

        //See tag status and do the needed.
        if($type == "open") {//The starting of the tag '<tag>'
            $parent[$level-1] = &$current;
            if(!is_array($current) or (!in_array($tag, array_keys($current)))) { //Insert New tag
                $current[$tag] = $result;
                if($attributes_data) $current[$tag. '_attr'] = $attributes_data;
                $repeated_tag_index[$tag.'_'.$level] = 1;

                $current = &$current[$tag];

            } else { //There was another element with the same tag name

                if(isset($current[$tag][0])) {//If there is a 0th element it is already an array
                    $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
                    $repeated_tag_index[$tag.'_'.$level]++;
                } else {//This section will make the value an array if multiple tags with the same name appear together
                    $current[$tag] = array($current[$tag],$result);//This will combine the existing item and the new item together to make an array
                    $repeated_tag_index[$tag.'_'.$level] = 2;
                    
                    if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well
                        $current[$tag]['0_attr'] = $current[$tag.'_attr'];
                        unset($current[$tag.'_attr']);
                    }

                }
                $last_item_index = $repeated_tag_index[$tag.'_'.$level]-1;
                $current = &$current[$tag][$last_item_index];
            }

        } elseif($type == "complete") { //Tags that ends in 1 line '<tag />'
            //See if the key is already taken.
            if(!isset($current[$tag])) { //New Key
                $current[$tag] = $result;
                $repeated_tag_index[$tag.'_'.$level] = 1;
                if($priority == 'tag' and $attributes_data) $current[$tag. '_attr'] = $attributes_data;

            } else { //If taken, put all things inside a list(array)
                if(isset($current[$tag][0]) and is_array($current[$tag])) {//If it is already an array...

                    // ...push the new element into that array.
                    $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result;
                    
                    if($priority == 'tag' and $get_attributes and $attributes_data) {
                        $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
                    }
                    $repeated_tag_index[$tag.'_'.$level]++;

                } else { //If it is not an array...
                    $current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
                    $repeated_tag_index[$tag.'_'.$level] = 1;
                    if($priority == 'tag' and $get_attributes) {
                        if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well
                            
                            $current[$tag]['0_attr'] = $current[$tag.'_attr'];
                            unset($current[$tag.'_attr']);
                        }
                        
                        if($attributes_data) {
                            $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data;
                        }
                    }
                    $repeated_tag_index[$tag.'_'.$level]++; //0 and 1 index is already taken
                }
            }

        } elseif($type == 'close') { //End of tag '</tag>'
            $current = &$parent[$level-1];
        }
    }
    
    return($xml_array);
}  
}
