<?php
/**
 * @class DerivedParamMgr
 * @version $Id: DerivedParamMgr.php 2914 2015-05-19 10:31:38Z elena $
 * 
 * 
 */

  class DerivedParamMgr extends AmdaObjectMgr {
 
     protected $type;
     protected $BaseManager;

     function __construct($type) {
		 
		parent::__construct('WsParams.xml');

		$this->type = $type;

		if ($type == 'derivedParam') {
		      $this->contentRootId = 'derivedParam-treeRootNode';
		      $this->contentRootTag = 'paramList';
//node attributes  and object XML tags 
		      $this->attributes = array('name' => '', 'buildchain' => '', 'timestep' => '');
// + tags in object XML
		      $this->optionalAttributes = array('units' => 'undefined','description' => 'undefined', 'ytitle' => 'undefined');
		      $this->objTagName = 'param';
		      $this->id_prefix = 'ws_';
		}
		elseif ($type == 'mySimuParam'){
		    $this->contentRootId = 'mySimuParam-treeRootNode';
		    $this->contentRootTag = 'mySimuParamList';
//node attributes and object XML tags 
		    $this->attributes = array('name' => '',  'size' => ' ', 'format' => '', 'desc' => '', 'mask' => '');
// + tags in object XML
		    $this->optionalAttributes = array('vi' => 'undefined', 'realvar' => '', 'fillvalue' => -1.e31, 'units' => 'undefined',
							'ytitle' => 'undefined', 'file' => '', 
							'type' => '', 'size' => '',  'minsampling' => '', 'plottype' => '');
		    $this->objTagName = 'mysimudata';
		    $this->id_prefix = 'simu_';		 		
		}
		elseif ($type == 'myWsrParam'){
		    $this->contentRootId = 'myWsrParam-treeRootNode';
		    $this->contentRootTag = 'myWsrParamList';
//node attributes and object XML tags 
		    $this->attributes = array('name' => '',  'size' => ' ', 'format' => '', 'desc' => '', 'mask' => '');
// + tags in object XML
		    $this->optionalAttributes = array('vi' => 'undefined', 'realvar' => '', 'fillvalue' => -1.e31, 'units' => 'undefined',
							'ytitle' => 'undefined', 'file' => '', 
							'type' => '', 'size' => '',  'minsampling' => '', 'plottype' => '');
		    $this->objTagName = 'mywsrdata';
		    $this->id_prefix = 'wsr_';		 		
		}
		else {
		      $this->contentRootId = 'myDataParam-treeRootNode';
		      $this->contentRootTag = 'myDataList';
//node attributes and object XML tags 
		      $this->attributes = array('name' => '',  'size' => ' ', 'format' => '', 'desc' => '', 'mask' => '', 'plottype' => '');
// + tags in object XML
		      $this->optionalAttributes = array('vi' => 'undefined', 'realvar' => '', 'fillvalue' => -1.e31, 'units' => 'undefined',
							'ytitle' => 'undefined',  'file' => '', 
							'type' => '', 'size' => '',  'minsampling' => '');
		      $this->objTagName = 'mydata';
		      $this->id_prefix = 'wsd_';
                      $this->type = 'myDataParam';
		}

		if (!file_exists($this->xmlName)) {
		      $this->createDom();
		      $this->xp = new domxpath($this->contentDom); 
	}
     }
   

    protected function param2dd($paramID){
	    $pairs = array(":" => "_");    
	    return strtr($paramID, $pairs); 
	  }

     protected function createDom() {
		$types = array('param' => 'derived', 'mydata' => 'myData', 'mysimudata' => 'mySimu', 'mywsrdata' => 'myWsr');

		$rootElement = $this->contentDom->createElement('ws');
                foreach ($types as $key => $value) {
 		    $contentId = $value.'Param-treeRootNode';
		    $contentTag = $key.'List';
		    $typeElement = $this->contentDom->createElement($contentTag);
		    $typeElement->setAttribute('xml:id', $contentId);
		    $rootElement->appendChild($typeElement);
		}
                $this->contentDom->appendChild($rootElement);
		$this->contentDom->save($this->xmlName);
        }
/*   
*      Internal resource file used by  DD applications
*/    
      protected function createObjectResource($obj){
// Parse : get real vars
		$myParser = new Parser();		
		$theChain = $obj->buildchain; 
		$newChain = $myParser->replaceAllButWS($theChain);
		$realVars = $myParser->getVars($newChain);
	
		$theTimeStep = $obj->timestep;
// Write stuff into internal res file

		$fd=fopen($this->resFileName, "w");
		foreach ($realVars as $theVar)  fprintf($fd, "%s ", $this->param2dd($theVar));
		fprintf($fd, "\n%s\n", $theTimeStep);
		fclose($fd);
		}

   
/*
*       rename PARAM in id.xml
*/
	protected function renameInResource($name, $id) {

            if (!file_exists(USERWSDIR.$id.'.xml')) return false; 
 
	    $this->objectDom -> load(USERWSDIR.$id.'.xml');
	    if (!($objToRename = $this->objectDom->getElementById($id))) return false; 
            $objToRename -> getElementsByTagName('name')->item(0)->nodeValue = $name; 
	    $this->objectDom ->save(USERWSDIR.$id.'.xml');
            
	    return true;
	 }


/*
*        Check file id.xml if difference is name only
*/
    protected function renameOnly($p) {

            $oldObject = new DomDocument("1.0");
            $oldObject -> load(USERWSDIR.$p->id.".xml");

            foreach ($p as $key => $value) {
                if ($key != 'id') {
                    if ($oldObject->getElementsByTagName($key)->length == 0) return false;
                    if ($key != "name" && $oldObject->getElementsByTagName($key)->item(0)->nodeValue != $value)
                                                                            return false;
                }
            }

        return true;
    }

/*****************************************************************
*                           PUBLIC FUNCTIONS
*****************************************************************/ 
/*
*         Create Parameter
*/
    public function createParameter($p, $folder){

            // overwritten                
            if ($this -> objectExistsByName($p->name)) {
                        $p -> id  = $this -> getObjectIdByName($p->name); 		      
                        $this -> deleteObject($p);
            }
        
            $this->id = $this->setId();
            if (!$this->id) return array('error' => ID_CREATION_ERROR);
            $this -> descFileName = USERWSDIR.$this->id.'.xml';
            
            $fileExists = -1;
            //if alias exists, replace alias name by parameter name   
            if ($this->type == 'derivedParam') {
                if (file_exists(USERWSDIR.'Alias.xml')) {
                                $p->buildchain =  $this->resetAlias($p->buildchain);
                }   
                // switch between myData and Derived 		
                $this -> resFileName = USERWORKINGDIR.$this->id.'.res';
                $this -> createObjectResource($p);
                $this -> createObjectDescription($p);
                $this -> addToContent($p, $folder);
                return array('id' => $this->id, 'info' => $p->buildchain);   
            }

            // myData parameter
            else {   
                 
                $isSpectra = $p->plottype === 'Spectra';
                $this->BaseManager = new BaseManager();
                $oldMask = $this->BaseManager->getOldMask($p->mask);	
  
                $myFileMgr = new FilesMgr();

                if($oldMask) {                                                                                                                              
                    $myFileMgr->delMask($oldMask);
                    $this->BaseManager->delVI($oldMask);                                     
                } 
                // separate files without mask - check that file exists
                else {
                      $fileExists = $this->BaseManager->getVI($p->mask);                      
                }

               if ($fileExists < 0) {
                    $p->vi = $this->BaseManager->addVI($p->mask, $p->format); 
                    $p->desc = $this->BaseManager->getViDesc($p->vi); 
                }
                else {
                   if (!$oldMask) {
                    $p->vi = $this->BaseManager->getVI($p->mask); 
                    $p->desc = $this->BaseManager->getViDesc($p->vi); 
                    }
                }

                if ($oldMask) {
                    $this->updateMaskMydata($oldMask, $p->mask,  $p->vi, $p->desc);
                }

                $this -> createObjectDescription($p);
                
                //Add table definition
                if (isset($p->tableDef))
                {
                	$tableNodes = $this->objectDom->getElementsByTagName('tableDef');
                	if ($tableNodes->length > 0)
                		$tableNode = $tableNodes->item(0);
                	else
                	{
                		$tableNode = $this->objectDom->createElement('tableDef');
                		$this->objectDom->documentElement->appendChild($tableNode);
                	}
                	//remove previous definition if exist
                	while ($tableNode->firstChild)
                		$tableNode->removeChild($tableNode->firstChild);
                	//add definition
                	$tableNode->setAttribute('tableDefType', $p->tableDef->tableDefType);
                	$tableNode->setAttribute('channelsDefType', $p->tableDef->channelsDefType);
                	if (isset($p->tableDef->data))
                	{
                		foreach ($p->tableDef->data as $key => $value)
                		{
                			$tablePropNode = $this->objectDom->createElement($key);
                			$tablePropNode->nodeValue = $value;
                			$tableNode -> appendChild($tablePropNode);
                		}
                	}
                	//save 
                	$this->objectDom->save($this->descFileName);
                }
                
                $this -> addToContent($p, $folder);

                $info =  "Size: ".$p->size."<br/>".$p->desc."<br/> Mask: ".$p->mask;

                if ($myFileMgr -> addMask($p->mask)){
                    return array('id' => $this->id, 'size' => $p->size, 'mask' => $p->mask, 'info' => $info, 'isSpectra' => $isSpectra, 'updateMyData' => true); 
                }
    
                return array('id' => $this->id, 'size' => $p->size, 'mask' => $p->mask, 'info' => $info, 'isSpectra' => $isSpectra);  
            }                
     } 

/*
*         Create new simu Parameter
*/
	public function createWsrParameter($p, $nodeType){
       // overwritten
            if ($nodeType) {                   
                    $this->contentRootId = $nodeType.'-treeRootNode';
                    $this->contentRootTag = $nodeType.'List';
                    if ($nodeType == 'mySimuParam') {
                        $this->objTagName = 'mysimudata';
                        $this->id_prefix = 'simu_'; 
                    }
                    else if ($nodeType == 'myWsrParam'){
                        $this->objTagName = 'mywsrdata';
                        $this->id_prefix = 'wsr_';             
                    }  
            }                  
	    $mySimuParam = $this->contentDom->getElementsByTagName($p->parentTag);
	    if($mySimuParam->length < 1){	
		    $rootElement = $this->contentDom->getElementsByTagName("ws")->item(0);
		    $typeElement = $this->contentDom->createElement($p->parentTag);
		    $typeElement->setAttribute('xml:id', $p->contentRootId);
		    $rootElement->appendChild($typeElement);
		    $this->contentDom->save($this->xmlName);
	    }

	    $this->id = $this->setId();
	    if (!$this->id) return array('error' => ID_CREATION_ERROR);

	    $this -> descFileName = USERWSDIR.$this->id.'.xml';
   
	    $this->BaseManager = new BaseManager();

	    $p->vi = $this->BaseManager -> addSimuVI($p); 
	    $p->desc = $this->BaseManager -> getViDesc($p->vi); 
	    
	    $dom = new DomDocument("1.0"); 
	    $dom->preserveWhiteSpace = false;
	    $dom->formatOutput = true;
	    
	    $root = $dom->createElement($this->objTagName); 
	    $root->setAttribute('xml:id',$this->id);

	      foreach($p as $key => $value) {
		if ($key != 'id' && $key != 'leaf' && $key != 'nodeType') {	
		     $node =  $dom->createElement($key,htmlspecialchars($value));
		    $root -> appendChild($node);
		}
	      }      
// add Optional Attributes if they are undefined	      
              foreach ($this->optionalAttributes as $key => $value)   
		 if ($root->getElementsByTagName($key)->length == 0) {
                        $node =  $dom->createElement($key,htmlspecialchars($value));  
			$root -> appendChild($node);
                  }
                  
	      $dom->appendChild($root);
	      $dom->save($this->descFileName);  
	    
	      
	    $this -> addToContent($p, $folder);
	    $info =  "Size: ".$p->size."<br/>".$p->desc;

	    return array('id' => $this->id, 'size' => $p->size, 'info' => $info);  
     } 

/*
*  Start-Stop was changed - update in in MyDataParam
*/ 
    public function updateMydata($mask, $desc) 
    {
        $mydatas = $this->xp->query("//mydata[@mask = '".$mask."']"); 
         
        if ($mydatas->length > 0) 
            foreach ($mydatas as $mydata)  
                $mydata->setAttribute("desc", $desc);  

         $this->contentDom->save($this->xmlName);
                 
    }   

/*
*      Mask was changed - update in MyDataParam   
*/
    public function updateMaskMydata($oldMask, $newMask, $viId, $description)
    {     
        $mydatas = $this->xp->query("//mydata[@mask = '".$oldMask."']");
        if ($mydatas->length == 0) return;

        foreach ($mydatas as $mydata)  
        {
                $id = $mydata->getAttribute('xml:id');
                $mydata->setAttribute("mask", $newMask); 
                $mydata->setAttribute("desc", $description);

                if (file_exists(USERWSDIR.$id.'.xml')) 
                {
                    $xml = new DomDocument("1.0");
                    $xml->load(USERWSDIR.$id.'.xml');

                    $mask = $xml->getElementsByTagName('mask');
                    $mask->item(0)->nodeValue = $newMask;

                    $vi = $xml->getElementsByTagName('vi');
                    $vi->item(0)->nodeValue = $viId;

                    $desc = $xml->getElementsByTagName('desc');
                    $desc->item(0)->nodeValue = $description; 
                    $xml->save(USERWSDIR.$id.'.xml');                        
                }
        }    
    }

/*
*        Delete Description, Resource file, mark deleted parameter AS UNDEFINED in requests/ conditions/ aliases (?)
*/
//TODO return to client number of requests touches???
	public function deleteParameter($id){ 
	//delete VI if there is no params with this mask ??????  
			$isDeletedMask = false;
			if ($this->type == 'myDataParam') {
			  if (file_exists(USERWSDIR.$id.'.xml')) {
			    $xml = new DomDocument("1.0");
			    $xml->load(USERWSDIR.$id.'.xml');
			    $mask = $xml->getElementsByTagName('mask'); 
			    if (!$mask) return;
			    $maskName = $mask->item(0)->nodeValue;
			    $params = $this->xp->query("//mydata[@mask='".$maskName."']"); 
			    if ($params->length == 1) {
				  $this->BaseManager = new BaseManager();
				  $this->BaseManager->delVI($maskName); 
				  $FilesMgr = new FilesMgr();
				  $FilesMgr->delMask($maskName);
				  $isDeletedMask = true;
				}                      
			    }
			}
			if (file_exists(USERWSDIR.$id.'.xml')) unlink(USERWSDIR.$id.'.xml');
			if (file_exists(USERWORKINGDIR.$id.'.res')) unlink(USERWORKINGDIR.$id.'.res');	
			$requestMgr = new RequestMgr();
			$n_requests = $requestMgr -> markAsUndefined($id);
			return $isDeletedMask;
        }
   
/*
*   Get Object into Edit
*/

    public function getObject($id) {
  	    
	     if (!file_exists(USERWSDIR.$id.'.xml')) return array('error' => NO_OBJECT_FILE); 
 
	    $this->objectDom -> load(USERWSDIR.$id.'.xml');
	    if (!($objToGet = $this->objectDom->getElementById($id))) return array('error' => NO_SUCH_ID); 
	           
	    $attributesToReturn['id'] = $objToGet->getAttribute('xml:id');
	    $attributes = $objToGet -> childNodes;
	    foreach($attributes as $attribute) {
		    if ($attribute->tagName === "buildchain") $attributesToReturn[$attribute->tagName] = $this->setAlias($attribute->nodeValue);
		    else if ($attribute->tagName === "tableDef")
		    {
		    	//load table definition
		    	$tableDefType = $attribute->getAttribute('tableDefType');
		    	$channelsDefType = $attribute->getAttribute('channelsDefType');
		    	$tableData = array();
		    	foreach ($attribute->childNodes as $tableDataNode)
		    	{
		    		if ($tableDataNode->nodeType != XML_ELEMENT_NODE)
		    			continue;
		    		$tableData[$tableDataNode->tagName] = $tableDataNode->nodeValue;
		    	}
		    	$attributesToReturn[$attribute->tagName] = array('tableDefType' => $tableDefType, 'channelsDefType' => $channelsDefType, 'data' => $tableData);
		    }
		    else $attributesToReturn[$attribute->tagName] =  $attribute->nodeValue;
	    }	
         
	  return  $attributesToReturn;   
    }
  
    function getObjectByName($name) {
    	 if (!$this->objectExistsByName($name))
    	 	return array('error' => NO_SUCH_ID);
			   $objId = $this->getObjectIdByName($name);
			   return $this->getObject($objId);
    }
    
    function validNameObject($p){
    	// overwritten
    	$res = parent::validNameObject($p);
    	
    	if (!$res['valid'])
    		return $res;
    	
    	//only low case
    	if (strtolower($p->name) != $p->name)
    		return array('valid' => false, 'error' => 'Use only low case');
    	
    	return array('valid' => true);
    }
}
?>