<?php
/**
* File containing the Image Class.
*
* @version 1.0 Initialisation of this file
* @since 1.0 Core application's file
* 
* @author Evan Pisani 'yogg at epsina . com'
* 
* @todo Complete the functions with errors detection and finish the descriptions
*/
use OpenCloud\Common\Error\BadResponseError;
use OpenCloud\Common\Error\BaseError;
use OpenCloud\Common\Error\NotImplementedError;
use OpenCloud\Common\Error\UserInputError;

include("CoreInterface.php");

/**
* Image Class of the back-end application
*
* Management of images
*
*/
class image implements Core{ 

	/** @var App $app protected, contains the main app object */
	protected $app;
	
	/** @var OpenStack\Identity $libClass protected, contains the library Identity object */
	protected $libClass;
	
	/**
	* Image constructor
	*
	* @param App $app the main app object
	*
	* @return Image
	*/
	public function __construct($app){
		if(!isset($app)){
			$this->app->setOutput("Error", "Incorrect parameter app");
		}
		$this->app = $app;
		$this->libClass = $app->getLibClass("Image");
	}


	/**
	* Execute an action
	*
	* @param String $action name of another function of this class
	*
	* @return void
	*/
	public function action($action){
		 $this->{$action.""}();	
	}

	/**
	* Create a new image
	*
	* @param array $opt Options for the image creation (name is required, others are optionals)
	*
	* @return Image
	*/
	private function createImage(){
		$opt = $this->app->getPostParam("opt");

		if(!isset($opt)){
			$this->app->setOutput("Error", "Incorrect parameter opt");
		}

		try{	
			$options = Array();

			// Check the image name
			if(isset($opt['name'])){ 
				$imagesList = $this->listImage();
				if(isset($imagesList)){
    				foreach($imagesList as $image){
    					if(strcmp($image->name, $opt['name']) == 0){ // if the image name already exists -> error
    						$this->app->setOutput("Error", "Image name already exists");
    					}
    				}
    			}
    			$options['name'] = $opt['name'];
			}
			else{
				$this->app->setOutput("Error", "Missing parameter 'name' for the new image");
			}

			//  Check optionals arguments
			if(isset($opt['id'])){ // UUID : nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn
				if($this->libClass->getImage($opt['id']) != null){ // if the id already exists -> error
					$this->app->setOutput("Error", "Image id already exists");
				}
				$options['id'] = $opt['id'];
			}
			if(isset($opt['visibility'])){ // public, private
				$options['visibility'] = $opt['visibility'];
			}
			if(isset($opt['tags'])){ // list
				$options['tags'] = $opt['tags'];
			}
			if(isset($opt['containerFormat'])){ // string : ami, ari, aki, bare, ovf, ova, docker
				$options['containerFormat'] = $opt['containerFormat'];
			}
			if(isset($opt['diskFormat'])){ // string : ami, ari, aki, vhd, vmdk, raw, qcow2, vdi, iso
				$options['diskFormat'] = $opt['diskFormat'];
			}
			if(isset($opt['minDisk'])){ //int
				$options['minDisk'] = $opt['minDisk'];
			}
			if(isset($opt['minRam'])){ // int
				$options['minRam'] = $opt['minRam'];
			}
			if(isset($opt['protected'])){ // boolean
				$options['protected'] = $opt['protected'];
			}
			if(isset($opt['properties'])){ // type dict 
				$options['properties'] = $opt['properties'];
			}	

			$image = $this->libClass->createImage($options);
		}catch(BadResponseError $e){
			$this->app->getErrorInstance()->BadResponseHandler($e);
        }catch(UserInputError $e){
			$this->app->getErrorInstance()->UserInputHandler($e);
        }catch(BaseError $e){
			$this->app->getErrorInstance()->BaseErrorHandler($e);
        }catch(NotImplementedError $e){
			$this->app->getErrorInstance()->NotImplementedHandler($e);
        }catch(Exception $e){
        	$this->app->getErrorInstance()->OtherException($e);
        }
		$this->app->setOutput("Images", $image);

	}

	/**
	* List the images of the server
	*
	* @return List of Image
	*/
	private function listImage(){
		try{
			$result = array();
			$l = $this->libClass->listImages();
			foreach($l as $tmp){
				$result[] = $tmp;
			}
		}catch(BadResponseError $e){
			$this->app->getErrorInstance()->BadResponseHandler($e);
        }catch(UserInputError $e){
			$this->app->getErrorInstance()->UserInputHandler($e);
        }catch(BaseError $e){
			$this->app->getErrorInstance()->BaseErrorHandler($e);
        }catch(NotImplementedError $e){
			$this->app->getErrorInstance()->NotImplementedHandler($e);
        }catch(Exception $e){
        	$this->app->getErrorInstance()->OtherException($e);
        }

		$this->app->setOutput("Images", $result);

	}

	/**
	* Details about an image
	*
	* @param String $id Identifier of the image
	*	
	* @return Image
	*/
	private function detailsImage(){
		$id = $this->app->getPostParam("id");

		if(!isset($id)){
			$this->app->setOutput("Error", "Incorrect id parameter"); 
		}
		else{
			try{
				$service = $this->libClass;
				$image = $service->getImage($id);
				if($image == null){ // if the image don't exists -> error
					$this->app->setOutput("Error", "Image doesn't exist");
				}
				else{
					$this->app->setOutput("Images", $image);
				}
			}catch(BadResponseError $e){
				$this->app->getErrorInstance()->BadResponseHandler($e);
	        }catch(UserInputError $e){
				$this->app->getErrorInstance()->UserInputHandler($e);
	        }catch(BaseError $e){
				$this->app->getErrorInstance()->BaseErrorHandler($e);
	        }catch(NotImplementedError $e){
				$this->app->getErrorInstance()->NotImplementedHandler($e);
	        }catch(Exception $e){
        		$this->app->getErrorInstance()->OtherException($e);
        	}
	    }
	}

	/**
	* Update informations about an image
	*
	* @param String $id id of the image
	* @param array  $opt Options for the image creation
	*	
	* @return Image
	*/

	private function updateImage(){
		$id = $this->app->getPostParam("id");
		$opt = $this->app->getPostParam("opt");

		if(!isset($id)){
			$this->app->setOutput("Error", "Incorrect id parameter"); 
		}
		else if(!isset($opt)){
			$this->app->setOutput("Error", "Incorrect opt parameter");
		}
		else{
			try{
				//vérifier existence image
				$service = $this->libClass;
				$image = $service->getImage($id);
				if($image == null){ // if the image don't exists -> error
					$this->app->setOutput("Error", "Image doesn't exist");
				}

				$options = Array();

				// Voir vérification des types
				if(isset($opt['name'])){ //string
					$options['name'] = $opt['name'];
				}
				if(isset($opt['minDisk'])){ //int
					$options['minDisk'] = $opt['minDisk'];
				}
				if(isset($opt['minRam'])){ // int
					$options['minRam'] = $opt['minRam'];
				}
				if(isset($opt['protected'])){ // boolean
					$options['protected'] = $opt['protected'];
				}
				if(isset($opt['visibility'])){ // public, private
					$options['visibility'] = $opt['visibility'];
				}
				if(isset($opt['tags'])){ // list
					$options['tags'] = $opt['tags'];
				}
				$image->update($options);
			}catch(BadResponseError $e){
				$this->app->getErrorInstance()->BadResponseHandler($e);
	        }catch(UserInputError $e){
				$this->app->getErrorInstance()->UserInputHandler($e);
	        }catch(BaseError $e){
				$this->app->getErrorInstance()->BaseErrorHandler($e);
	        }catch(NotImplementedError $e){
				$this->app->getErrorInstance()->NotImplementedHandler($e);
	        }catch(Exception $e){
	        	$this->app->getErrorInstance()->OtherException($e);
	        }
			$this->app->setOutput("Images", $image);
		}
	}

	/**
	* Delete an image
	*
	* @param String $id Identifier of the image
	*	
	* @return void
	*/
	private function deleteImage(){
		// si protected = true, demander de le mettre a false
		// vérifier existence image
		$id = $this->app->getPostParam("id");
		if(!isset($id)){
			$this->app->setOutput("Error", "Image doesn't exist");
		}
		else{
			try{
				$service = $this->libClass;
				$image = $this->libClass->getImage($id);
				if($image == null){ // if the image doesn't exists -> error
					$this->app->setOutput("Error", "Image doesn't exist");
				}
				$image->delete();
			}catch(BadResponseError $e){
				$this->app->getErrorInstance()->BadResponseHandler($e);
	        }catch(UserInputError $e){
				$this->app->getErrorInstance()->UserInputHandler($e);
	        }catch(BaseError $e){
				$this->app->getErrorInstance()->BaseErrorHandler($e);
	        }catch(NotImplementedError $e){
				$this->app->getErrorInstance()->NotImplementedHandler($e);
	        }catch(Exception $e){
	        	$this->app->getErrorInstance()->OtherException($e);
	        }	
	    }
	}

	/**
	* Resactive an image
	*
	* @param String $id Identifier of the image
	*	
	* @return void
	*/
	private function reactivateImage(){
		$id = $this->app->getPostParam("id");

		if(!isset($id)){
			$this->app->setOutput("Error", "Incorrect parameter");
		}
		else
		{
			try{
				$service = $this->libClass;
				$image = $service->getImage($id);
				if($image == null){ // if the image don't exists -> error
					$this->app->setOutput("Error", "Image doesn't exist");
				}

				$image->reactivate();
			}catch(BadResponseError $e){
				$this->app->getErrorInstance()->BadResponseHandler($e);
	        }catch(UserInputError $e){
				$this->app->getErrorInstance()->UserInputHandler($e);
	        }catch(BaseError $e){
				$this->app->getErrorInstance()->BaseErrorHandler($e);
	        }catch(NotImplementedError $e){
				$this->app->getErrorInstance()->NotImplementedHandler($e);
	        }catch(Exception $e){
	        	$this->app->getErrorInstance()->OtherException($e);
	        }
	    }
	}

	/**
	* Desactive an image
	*
	* @param String $id Identifier of the image
	*
	* @return void	
	*/
	private function desactivateImage(){
		$id = $this->app->getPostParam("id");

		if(!isset($id)){
			$this->app->setOutput("Error", "Incorrect parameter");
		}
		else
		{
			try{
				// vérifier existence image
				$service = $this->libClass;
				$image = $service->getImage($id);
				if($image == null){ // if the image don't exists -> error
					$this->app->setOutput("Error", "Image doesn't exist");
				}
				$image->deactivate();
			}catch(BadResponseError $e){
				$this->app->getErrorInstance()->BadResponseHandler($e);
	        }catch(UserInputError $e){
				$this->app->getErrorInstance()->UserInputHandler($e);
	        }catch(BaseError $e){
				$this->app->getErrorInstance()->BaseErrorHandler($e);
	        }catch(NotImplementedError $e){
				$this->app->getErrorInstance()->NotImplementedHandler($e);
	        }catch(Exception $e){
	        	$this->app->getErrorInstance()->OtherException($e);
	        }
	    }
	}

	/**
	* Upload an image
	*
	* @param String $id Identifier of the image
	* @param String $file_name Path of the image
	*	
	* @return void
	*/
	private function uploadImage(){
		$id = $this->app->getPostParam("id");
		$file_name = $this->app->getPostParam("file_name");
        $file = $this->app->getPostParam("file");
		error_log(print_r($file, true), 0);
	
		if(!isset($id)){
			$this->app->setOutput("Error", "Incorrect id parameter");
		}
		else if(!isset($file_name)){
			$this->app->setOutput("Error", "Incorrect file name parameter");
		}
		else{
			try{
				// vérifier existence image
				$service = $this->libClass;
				$image  = $service->getImage($id);
				if($image == null){ // if the image don't exists -> error
					$this->app->setOutput("Error", "Image doesn't exist");
				}
				$stream = \GuzzleHttp\Psr7\stream_for($file);
				$image->uploadData($stream);
			}catch(BadResponseError $e){
				$this->app->getErrorInstance()->BadResponseHandler($e);
	        }catch(UserInputError $e){
				$this->app->getErrorInstance()->UserInputHandler($e);
	        }catch(BaseError $e){
				$this->app->getErrorInstance()->BaseErrorHandler($e);
	        }catch(NotImplementedError $e){
				$this->app->getErrorInstance()->NotImplementedHandler($e);
	        }catch(Exception $e){
        		$this->app->getErrorInstance()->OtherException($e);
        	}
        }
	}

	/**
	* Download an image
	*
	* @param String $id Identifier of the image
	*
	* @return Stream
	*/
	private function downloadImage(){
		$id = $this->app->getPostParam("id");

		if(!isset($id)){
			$this->app->setOutput("Error", "Incorrect id parameter");
		}
		else{
			try{
				// vérifier existence image 
				$service = $this->libClass;
				$image  = $service->getImage($id);
				if($image == null){ // if the image don't exists -> error
					$this->app->setOutput("Error", "Image doesn't exist");
				}
				$stream = $image->downloadData();
			}catch(BadResponseError $e){
				$this->app->getErrorInstance()->BadResponseHandler($e);
	        }catch(UserInputError $e){
				$this->app->getErrorInstance()->UserInputHandler($e);
	        }catch(BaseError $e){
				$this->app->getErrorInstance()->BaseErrorHandler($e);
	        }catch(NotImplementedError $e){
				$this->app->getErrorInstance()->NotImplementedHandler($e);
	        }catch(Exception $e){
        		$this->app->getErrorInstance()->OtherException($e);
        	}
	        $this->app->setOutput("Images", $stream);
	    }
	}

	/**
	* Add a member to image
	*
	* @param String $image_id Identifier of the image
	* @param String $member_id Identifier of the member
	*	
	* @return Member
	*/
	private function addMemberImage(){
		$image_id = $this->app->getPostParam("image_id");
		$member_id = $this->app->getPostParam("member_id");

		if(!isset($image_id)){
			$this->app->setOutput("Error", "Incorrect image id parameter");
		}
		else if(!isset($member_id)){
			$this->app->setOutput("Error", "Incorrect member id parameter");
		}
		else{
			try{
				$service = $this->libClass;	

				$image  = $service->getImage($id);
				if($image == null){ // if the image don't exists -> error
					$this->app->setOutput("Error", "Image doesn't exist");
				}
				$member_id = $image->addMember($member_id);
				$this->app->setOutput("Images", $member_id);
			}catch(BadResponseError $e){
				$this->app->getErrorInstance()->BadResponseHandler($e);
	        }catch(UserInputError $e){
				$this->app->getErrorInstance()->UserInputHandler($e);
	        }catch(BaseError $e){
				$this->app->getErrorInstance()->BaseErrorHandler($e);
	        }catch(NotImplementedError $e){
				$this->app->getErrorInstance()->NotImplementedHandler($e);
	        }catch(Exception $e){
	        	$this->app->getErrorInstance()->OtherException($e);
	        }
	    }
	}

	
	/**
	* List members of an image
	*
	* @param String $image_id identifier of the image
	*
	* @return List of Member 	
	*/
	private function listMemberImage(){
		$image_id = $this->app->getPostParam("image_id");
		$member_id = $this->app->getPostParam("member_id");

		if(!isset($image_id)){
			$this->app->setOutput("Error", "Incorrect image id parameter");
		}
		else if(!isset($member_id)){
			$this->app->setOutput("Error", "Incorrect member id parameter"); 
		}
		else{
			try{
				// vérifier existence image
				$service = $this->libClass;
				$image = $service->getImage($image_id);
				if($image == null){ // if the image don't exists -> error
					$this->app->setOutput("Error", "Image doesn't exist"); 
				}
				$members = $image->listMembers();
				if($members == null){ // if the image don't exists -> error
					$this->app->setOutput("Error", "No member");
				}
			}catch(BadResponseError $e){
				$this->app->getErrorInstance()->BadResponseHandler($e);
	        }catch(UserInputError $e){
				$this->app->getErrorInstance()->UserInputHandler($e);
	        }catch(BaseError $e){
				$this->app->getErrorInstance()->BaseErrorHandler($e);
	        }catch(NotImplementedError $e){
				$this->app->getErrorInstance()->NotImplementedHandler($e);
	        }catch(Exception $e){
	        	$this->app->getErrorInstance()->OtherException($e);
	        }
			$this->app->setOutput("Images", $members);
		}
	}

	/**
	* Show details of a member of an image
	*
	* @param String $image_id Identifier of the image
	* @param String $member_id Identifier of the member
	*
	* @return Member
	*/
	private function detailMemberImage(){
		$image_id = $this->app->getPostParam("image_id");
		$member_id = $this->app->getPostParam("member_id");

		if(!isset($image_id)){
			$this->app->setOutput("Error", "Incorrect image id parameter"); 
		}
		else if(!isset($member_id)){
			$this->app->setOutput("Error", "Incorrect member id parameter");
		}
		else{
			try{
				$service = $this->libClass;	

				$image  = $service->getImage($id);
				if($image == null){ // if the image don't exists -> error
					$this->app->setOutput("Error", "Image doesn't exist");
				}

				$member = $image->getMember($member_id);
				if($member == null){ // if the member don't exists -> error
					$this->app->setOutput("Error", "Member doesn't exist");
				}
			}catch(BadResponseError $e){
				$this->app->getErrorInstance()->BadResponseHandler($e);
	        }catch(UserInputError $e){
				$this->app->getErrorInstance()->UserInputHandler($e);
	        }catch(BaseError $e){
				$this->app->getErrorInstance()->BaseErrorHandler($e);
	        }catch(NotImplementedError $e){
				$this->app->getErrorInstance()->NotImplementedHandler($e);
	        }catch(Exception $e){
	        	$this->app->getErrorInstance()->OtherException($e);
	        }
			$this->app->setOutput("Images", $member);
		}
	}
	
	/**
	* Remove a member of an image
	*
	* @param String $image_id Identifier of the image
	* @param String $member_id Identifier of the member
	*	
	* @return void
	*/
	private function removeMemberImage(){
		$image_id = $this->app->getPostParam("image_id");
		$member_id = $this->app->getPostParam("member_id");

		if(!isset($image_id)){
			$this->app->setOutput("Error", "Incorrect image id parameter"); 
		}
		else if(!isset($member_id)){
			$this->app->setOutput("Error", "Incorrect member id parameter");
		}
		else{
			try{
				$service = $this->libClass;	

				$image  = $service->getImage($id);
				if($image == null){ // if the image don't exists -> error
					$this->app->setOutput("Error", "Image doesn't exist");
				}	
				$member = $image->getMember($member_id);
				if($member == null){ // if the image don't exists -> error
					$this->app->setOutput("Error", "Member doesn't exist");
				}
				$member->delete();
			}catch(BadResponseError $e){
				$this->app->getErrorInstance()->BadResponseHandler($e);
	        }catch(UserInputError $e){
				$this->app->getErrorInstance()->UserInputHandler($e);
	        }catch(BaseError $e){
				$this->app->getErrorInstance()->BaseErrorHandler($e);
	        }catch(NotImplementedError $e){
				$this->app->getErrorInstance()->NotImplementedHandler($e);
	        }catch(Exception $e){
	        	$this->app->getErrorInstance()->OtherException($e);
	        }
	    }
	}

	/**
	* Update a member of an image
	*
	* @param String $image_id Identifier of the image
	* @param String $member_id Identifier of the member
	* @param String $status New status for the member
	*
	* @return void	
	**/
	private function updateMemberImage(){
		$image_id = $this->app->getPostParam("image_id");
		$member_id = $this->app->getPostParam("member_id");
		$status = $this->app->getPostParam("status");

		if(!isset($image_id)){
			$this->app->setOutput("Error", "Incorrect image id parameter");
		}
		else if(!isset($member_id)){
			$this->app->setOutput("Error", "Incorrect member id parameter");
		}
		else{
			try{
				$service = $this->libClass;		

				$image  = $service->getImage($id);
				if($image == null){ // if the image don't exists -> error
					$this->app->setOutput("Error", "Image doesn't exist");
				}
				$member = $image->getMember($member_id);
				if($member == null){ // if the member don't exists -> error
					$this->app->setOutput("Error", "Member doesn't exist");
				}
				$member->updateStatus($status);
			}catch(BadResponseError $e){
				$this->app->getErrorInstance()->BadResponseHandler($e);
	        }catch(UserInputError $e){
				$this->app->getErrorInstance()->UserInputHandler($e);
	        }catch(BaseError $e){
				$this->app->getErrorInstance()->BaseErrorHandler($e);
	        }catch(NotImplementedError $e){
				$this->app->getErrorInstance()->NotImplementedHandler($e);
	        }catch(Exception $e){
	        	$this->app->getErrorInstance()->OtherException($e);
	        }
      	}
	}

}
?>