<?php

class InstallationManager {
 
 	private $file;
 	static private $instance=null;
 	private $ch;
 	
 	static public function getInstance(){
 		if(self::$instance==null) self::$instance = new InstallationManager();
 		return self::$instance;
 	}
 	 
	public function __construct(){
		$this->file = new File();
	}
	
	public function getRemoteInstallations(){

		$fileURL = Config::get("remoteUpgradesURL", "upgradesInfo");
		$fileURL .= "?a=getInstallations";
		 
		if(function_exists("curl_init")){
			$content = $this->getRemoteContent($fileURL);
		}else{
		 	Response::sendBackendMessageResponse("Error: curl_init() function does not exist.");	
		}
		
		if($content===false){
		 	Response::sendBackendMessageResponse("Connection cannot be established.\n"."Curl error: " . curl_error($this->ch));
		}else{
		 	$retArr = WddxSerializer::deserialize($content);
			Response::sendOKResponse($retArr);
		}

	}
	

	public function getLocalInstallations(){
	 	
		$basePath = Config::get("private_path")."/applications_installations";
		//$ud = new UD();
	 	$this->file->readOnlyDirs = true;
	 	$FaF = $this->file->getFoldersAndFiles($basePath);

		$retArr = array();
		
		for ($i=0; $i<count($FaF); $i++){
		  	$path = $basePath . "/" . $FaF[$i][name] . "/installationInfo.xml";
			$content = Util::readFile($path);
			$installationInfo = WddxSerializer::deserialize($content);
			$installationInfo->_installationDirectory = $FaF[$i][name];
			$retArr[] = $installationInfo;
		}
		
		Response::sendOKResponse($retArr);
	
	}
	
	public function installApplication($d){
	 
	 	// input
		//$d->applicationName;
		//$d->installationDirectoryName;
		//$d->location; // Local/Remote*/


		$retObj = (object) array();
		$retObj->success = $this->installApplication_Private($d->applicationName, $d->installationDirectoryName, $d->location, $d->licenseKey, true);
		
		$applXmlSrt = Util::readFile(Config::get("private_system_path")."/modules/applicationsInfo.xml");
		$retObj->applicationsInfo  = WddxSerializer::deserialize($applXmlSrt);
		
		Response::sendOKResponse($retObj);
		
	}
	
	private function installApplication_Private($applicationName, $installationDirectoryName, $location, $licenseKey, $forceExtensionUpdate=false){

		
		if($location=="Local"){
		 	//echo "Local \n";
			$sourcePath = Config::get("private_path")."/applications_installations"."/".$installationDirectoryName;
			$applcaitionInfoPath = $sourcePath."/installationInfo.xml";
			$installApplXmlStr = Util::readFile($applcaitionInfoPath);
			$installApplObj = WddxSerializer::deserialize($installApplXmlStr);
		}else if($location=="Remote"){
		 	//echo "Remote \n";
		 	$sourcePath = Config::get("remoteUpgradesURL", "upgradesInfo");
		 	$http_get_data = array('a'=>'getFile',
					              'lk'=>$licenseKey,
					              'fp'=>$installationDirectoryName);

			$sourcePath .= "?".http_build_query($http_get_data, "", "&");
			$applcaitionInfoPath = $sourcePath."/installationInfo.xml";
			//echo $applcaitionInfoPath;
			$remoteResponse = $this->getRemoteContent($applcaitionInfoPath);
			if(substr($remoteResponse, 0, 5)=="ERROR"){
			 	//echo $remoteResponse;
				if($remoteResponse=="ERROR_LICENSE"){
					Response::sendBackendMessageResponse("License key is wrong.");	
				}
				if($remoteResponse=="ERROR_WRONG_FILEPATH"){
				 	Response::sendBackendMessageResponse("Filepath is not acceptable.");
				}
				EXIT();
			}
		
			$installApplObj = WddxSerializer::deserialize($remoteResponse);
		}
		else{
		 	return;
		}

		
		// ---------------------------------------
		// - add license
		// ---------------------------------------
		// 
		if(!empty($licenseKey)){
			$installApplObj->licenseKey = $licenseKey;
		}
		
		

		
		// ---------------------------------------
		// 1. copy modules files
		// ---------------------------------------
		if(is_array($installApplObj->moduleFiles)){
		 	//echo "moduleFiles \n";
			for($i=0; $i<count($installApplObj->moduleFiles); $i++){
				$from = $sourcePath."/".$installApplObj->moduleFiles[$i];
				$relativePath = $installApplObj->directoryName."/".$installApplObj->moduleFiles[$i];
				$to = Config::get("private_system_path")."/modules/".$relativePath;
				$this->file->createAbsolutePath(Config::get("private_system_path")."/modules", substr($relativePath , 0, strrpos($relativePath , "/")));
				//echo "from: " . $from . "\n";
			 	//echo "to: ". $to . "\n";
				$this->copyInstallationFile($from, $to, $location);
			}
		}
	
		// ---------------------------------------
		// 2. copy system files
		// ---------------------------------------
		if(is_array($installApplObj->systemFiles)){
		 	//echo "systemFiles \n";
			for($i=0; $i<count($installApplObj->systemFiles); $i++){
				$from = $sourcePath."/".$installApplObj->systemFiles[$i];
				$to = $installApplObj->systemFiles[$i];
				//echo "from: " . $from . "\n";
			 	//echo "to: ". $to . "\n";
				$this->file->createRelativePath(substr($relativePath , 0, strrpos($relativePath , "/")));
				$this->copyInstallationFile($from, $to, $location);
			}
		}
	
		// ---------------------------------------
		// 3. add application to applicationInfo.xml
		// ---------------------------------------
		$applXmlSrt = Util::readFile(Config::get("private_system_path")."/modules/applicationsInfo.xml");
		$applArr = WddxSerializer::deserialize($applXmlSrt);
		$exist=false;
		for($i=0; $i<count($applArr); $i++){
			if($applArr[$i]->name ==  $installApplObj->name){
			 	//echo "exist \n";
			 	$exist=true;
				$applArr[$i] = $installApplObj;
			}
		}
		if(!$exist){
			//echo "!exist \n";
			$applArr[] = $installApplObj;	
		}
		Util::writeFile(Config::get("private_system_path")."/modules/applicationsInfo.xml", WddxSerializer::serialize($applArr));
		
		// ---------------------------------------
		// retrive all users 
		// ---------------------------------------
		Indexes::setIndexesDirectory(Config::get("private_system_indexes_path"));
		$allUsersArr = array_keys(Indexes::getArray("user_group"));
		
		// ---------------------------------------
		// copy user files (must execute after step 3.)
		// ---------------------------------------
		

		for($i=0; $i<count($allUsersArr); $i++){
		 	//echo $allUsersArr[$i]." \n";
			User::getInstance()->copyAllApplicationsUserFiles($allUsersArr[$i], $installApplObj->name);
		}
		
		// ---------------------------------------
		// update applcaition association (must execute after step 3.)
		// ---------------------------------------
		for($i=0; $i<count($allUsersArr); $i++){
			//echo $allUsersArr[$i]." \n";
			User::getInstance()->updateAllApplicationAssociation($allUsersArr[$i], $installApplObj->name);
		}

		return true;
		
	}
	
	function copyInstallationFile($from, $to, $location){
	 
		global $ud;
		
		if($location == "Remote"){
			$content = $this->getRemoteContent($from);
			if($content==false) return false;
			else Util::writeFile($to, $content);
		}elseif($location == "Local"){
			return $this->file->copy($from, $to, true);
		}else {
			return false; 
		}
	}
	
	
		
	function getRemoteContent($url){
		
		
		$this->ch = curl_init();
		curl_setopt($this->ch, CURLOPT_URL, $url);
		
		/*curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);*/
		
		curl_setopt($this->ch, CURLOPT_FOLLOWLOCATION, true);
		curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($this->ch, CURLOPT_POST, TRUE);

		$data = curl_exec($this->ch);
		curl_close($this->ch);
		
		return $data;
		
	}
	
	/*
	
	
	function getFirstTimeModules($d){
	 
	 	global $wddx;
	 	
	 	$applXmlSrt = Util::readFile("resources/modules/applications.xml");
	 	if($applXmlSrt==false){
	 		Response::sendResponse(false, null);
	 	}
	 	
	 	$applArray = $wddx->deserialize($applXmlSrt);

		
 		Response::sendOKResponse($applArray);
 		
	}	
	
	function installUpgrade($d){
	 
	 	global $user,$config;
	 	
	 	$retObj= (object) array();
	 	
	 	if($d->upgradesLocation=="local"){
			$sourceDir = "upgrades/".$d->upgrade->dir."/v".$d->upgrade->version;
			$retObj->success = $this->_installApplication($sourceDir);
			$retObj->config = $user->getConfig(false);
			Response::sendOKResponse($retObj);
		}else if($d->upgradesLocation=="remote"){
			$sourceDir = $config->upgradesInfo->remoteUpgradesURL."/v".$d->upgrade->version."/".$d->upgrade->dir;
			$retObj->success = $this->_installApplication($sourceDir, null, false, true);
			$retObj->config = $user->getConfig(false);
			Response::sendOKResponse($retObj);
		}
	
		exit;
	 	
	}
	function copyInstallationFile($from, $to, $isRemote){
	 
		global $ud;
		
		if($isRemote==true){
			//$content = file_get_contents($from);
			//$content = implode('', file($from));
			$content = Util::httpSocketConnection($from);
			if($content==false) return false;
			else Util::writeFile($to, $content);
		}else{
			return $ud->copy($from, $to, true);
		}
	}
			
	function _installApplication($sourceDir, $installApplObj=null, $forceExtensionUpdate=false, $isRemote=false){
		
		global $config, $ds, $wddx, $ud, $file, $auth;
		
		if($installApplObj==null){
			if($isRemote){
				//$installApplXmlStr = file_get_contents($sourceDir."/installation.xml");
				//$installApplXmlStr = implode('', file($sourceDir."/installation.xml"));
				$installApplXmlStr = Util::httpSocketConnection($sourceDir."/installation.xml");
			}else{
				$installApplXmlStr = Util::readFile($sourceDir."/installation.xml");
			}
		
			$installApplObj = $wddx->deserialize($installApplXmlStr);
		}
		
		// ---------------------------------------
		// copy modules files
		if(is_array($installApplObj->moduleFiles)){
			for($i=0; $i<count($installApplObj->moduleFiles); $i++){
				$from = $sourceDir."/".$installApplObj->moduleFiles[$i];
				$relativePath = $installApplObj->directoryName."/".$installApplObj->moduleFiles[$i];
				$to = $config->private_system_path."/modules/".$relativePath;
				$file->createAbsolutePath($config->private_system_path."/modules", substr($relativePath , 0, strrpos($relativePath , "/")));
				echo ($from );
				echo ("\n<br />\n" );
				echo ($to );
				echo ("\n<br />\n" );
				$this->copyInstallationFile($from, $to, $isRemote);
			}
		}
	
		// ---------------------------------------
		// copy system files
		if(is_array($installApplObj->systemFiles)){
			for($i=0; $i<count($installApplObj->systemFiles); $i++){
				$from = $sourceDir."/".$installApplObj->systemFiles[$i];
				$to = $installApplObj->systemFiles[$i];
				$file->createRelativePath(substr($relativePath , 0, strrpos($relativePath , "/")));
				$this->copyInstallationFile($from, $to, $isRemote);
			}
		}
		
		// ---------------------------------------
		// update or add applicationAssociation.xml
		if(is_array($installApplObj->recommendedExtensions)){
			$aaPath = $config->private_system_path."/config/users/".$auth->userInfo->username."_aa.txt";
		 	$aaXmlSrt = Util::readFile($aaPath);
			$aaObj = $ds->deserialize($aaXmlSrt);
		 	for($i=0; $i<count($installApplObj->recommendedExtensions); $i++){
				$ext = $installApplObj->recommendedExtensions[$i];
				if($forceExtensionUpdate==true || ($forceExtensionUpdate==false && empty($aaObj->$ext)))
					$aaObj->$ext = $installApplObj->name;
			}
			Util::writeFile($aaPath, $ds->serialize($aaObj));
		}

		// ---------------------------------------
		// add application to applicationInfo.xml
		$applXmlSrt = Util::readFile($config->private_system_path."/modules/applicationsInfo.xml");
		$applArr = $wddx->deserialize($applXmlSrt);
		$exist=false;
		for($i=0; $i<count($applArr); $i++){
			if($applArr[$i]->name ==  $installApplObj->name){
			 	$exist=true;
				$applArr[$i] = $installApplObj;
			}
		}
		if(!$exist){
			$applArr[] = $installApplObj;	
		}
		Util::writeFile($config->private_system_path."/modules/applicationsInfo.xml", $wddx->serialize($applArr));
		
		
		// add application to user object
		$auth->addApplicationToUserInfo($installApplObj->name);
		
		
		return true;
		
	}
	function getLocalUpdateInformations(){
	 
		global $config, $ds, $wddx,  $ud, $file;
		
		$retObj = (object) array();
		$filePath = $config->upgradesInfo->localUpgradesPath ."/". $config->upgradesInfo->upgradesXML ;
		if(is_file($filePath)){
		 	$retObj->upgrades = $wddx->deserialize(Util::readFile($filePath));
			$retObj->success = true;
		}else{
			$retObj->success = false;	
		}
				
		Response::sendOKResponse($retObj);
	 	
	}
	function getRemoteUpdateInformations($d){
	 
		global $config, $ds, $wddx, $ud, $file;
		
		$retObj = (object) array();
		if(empty($d->versionDir)){
			$fileURL = $config->upgradesInfo->remoteUpgradesURL ."/". $config->upgradesInfo->upgradesXML;
		}else{
		 	$fileURL = $config->upgradesInfo->remoteUpgradesURL ."/".$d->versionDir."/". $config->upgradesInfo->upgradesXML;
		}
		
		//$content = file_get_contents($fileURL);
		//$content = implode('', file($fileURL));
		$content = Util::httpSocketConnection($fileURL);
		
		if($content!=false){
		 	$retObj->upgrades = $wddx->deserialize($content);
			$retObj->success = true;
		}else{
			$retObj->success = false;	
		}
				
		Response::sendOKResponse($retObj);
	 	
	}
	function installApplication($d){
	 
	 	global $config, $ds, $ud, $file;
	 	
	 	$sourceDir = "resources/modules/".$d->directoryName;

		$retObj= (object) array();
		$retObj->success = $this->_installApplication($sourceDir, null, true);
		
		Response::sendOKResponse($retObj);
		
	}
	function installApplications($d){
	 
	 	global $config, $ds, $ud, $file;
	 	
	 	
		$retObj = (object) array();
		$retObj->success = true;
		foreach($d as $key=>$applInfo){
		 	$sourceDir = "resources/modules/".$applInfo->directoryName;
			$retObj->success = ($retObj->success && $this->_installApplication($sourceDir, $applInfo, true));
		}
		
		Response::sendOKResponse($retObj);
		
	}
	*/
}

?>