<?php
/**
* File containing the compute Class.
*
* @version 1.0 Initialisation of this file
* @since 1.0 Core application's file
* 
* @author  bhupi
* 
*/

use OpenCloud\Common\Error;

include("CoreInterface.php");
/**
* Compute Class of the back-end application
*
* Management of Servers
*
*/
class compute implements Core
{
	/** @var App $app protected, contains the main app object */
	protected $app;

	/** @var OpenStack\Compute $libClass protected, contains the library Compute object */
	protected $libClass;


	/**
	* Compute constructor
	*
	* @param App $args the main app object
	*
	* @return compute Object
	*/
	public function __construct($app)
	{
		$this->app = $app;
		$this->libClass = $app->getLibClass("Compute");
	}
	
	/**
	* Execute an action
	*
	* @param String $action name of another function of this class
	*
	* @return void
	*/
	public function action($action){
		
		$this->{$action.""}();
		
	}
	
	/**
	* List servers.
	*
	* @return void
	*/
	public function listServers()
	{
		try{
			$serverList = $this->libClass->listServers(true);
			$servers = Array();
			foreach($serverList as $server){
				$servers[$server->id] = Array();
				$server->flavor->retrieve();
				$server->image->retrieve();
				$server->retrieve();
				$servers[$server->id]["id"]  = $server->id;
				$servers[$server->id]["name"] = $server->name;
				$servers[$server->id]["image"] = $server->image; 
				$servers[$server->id]["ram"] = $server->flavor->ram;
				$servers[$server->id]["disk"] = $server->flavor->disk;
				$servers[$server->id]["flavor"] = $server->flavor; 
				$servers[$server->id]["status"] = $server->status;
				$servers[$server->id]["created"] = $server->created;
				$servers[$server->id]["updated"] = $server->updated;
				$servers[$server->id]["ipv4"] = $server->ipv4;
				$servers[$server->id]["ipv6"] = $server->ipv6;
				$servers[$server->id]["progress"] = $server->progress;
				$servers[$server->id]["hostId"] = $server->hostId;
				$servers[$server->id]["tenantId"] = $server->tenantId;
				$servers[$server->id]["userId"] = $server->userId;
				$servers[$server->id]["taskState"] = $server->taskState;
				$servers[$server->id]["addresses"] = $server->addresses;
				$servers[$server->id]["links"] = $server->links;
				$servers[$server->id]["metadata"] = $server->metadata;
			}
			$this->app->setOutput("Servers", $servers);
		}
		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 flavors.
	*
	* @return void
	*/
	public function listFlavors()
	{
		try{
			$flavorList = $this->libClass->listFlavors();
			$flavors = Array();
			foreach($flavorList as $flavor){
				$flavors[$flavor->id] = Array();
				$flavor->retrieve();
				$flavors[$flavor->id]["id"]  = $flavor->id;
				$flavors[$flavor->id]["name"] = $flavor->name;
				$flavors[$flavor->id]["ram"] = $flavor->ram;
				$flavors[$flavor->id]["disk"] = $flavor->disk;
				$flavors[$flavor->id]["vcpus"] = $flavor->vcpus;
				$flavors[$flavor->id]["links"] = $flavor->links;
			}
			$this->app->setOutput("Flavors", $flavors);
		}
		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 images.
	*
	* @return void
	*/
	public function listImages()
	{
		try{
			$imageList = $this->libClass->listImages();
			$images = Array();
			foreach($imageList as $image){
				$images[$image->id] = Array();
				$image->retrieve();
				$images[$image->id]["id"]  = $image->id;
				$images[$image->id]["name"] = $image->name;
				$images[$image->id]["status"] = $image->status;
				$images[$image->id]["created"] = $image->created;
				$images[$image->id]["updated"] = $image->updated;
				$images[$image->id]["minDisk"] = $image->minDisk;
				$images[$image->id]["minRam"] = $image->minRam;
				$images[$image->id]["progress"] = $image->progress;
				$images[$image->id]["links"] = $image->links;
				$images[$image->id]["metadata"] = $image->metadata;
			}
			$this->app->setOutput("Images", $images);
		}
		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);
		}
	}
	
	/**
	* Get server details.
	*
	* @return void
	*/
	public function getServer()
	{
		try{
			$serverId = $this->app->getPostParam("serverId");
			if(!isset($serverId)){
				$this->app->setOutput("Error", "Server ID is missing!");
				return;
			}
			$opt = array('id' => $serverId);
			$server = $this->libClass->getServer($opt);
			$server->retrieve();
			$this->app->setOutput("MyServer", $server);
		}
		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);
		}
	}
	
	/**
	* Get flavor details.
	*
	* @return void
	*/
	public function getFlavor()
	{
		try{
			$flavorId = $this->app->getPostParam("flavorId");
			if(!isset($serverId)){
				$this->app->setOutput("Error", "Flavor ID is missing!");
				return;
			}
			$opt = array('id' => $flavorId);
			$flavor = $this->libClass->getFlavor($opt);
			$flavor->retrieve();
			$this->app->setOutput("MyFlavor", $flavor);
		}
		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);
		}
	}
	
	/**
	* Get image details.
	* @return array
	*/
	public function getImage()
	{
		try{
			$imageId = $this->app->getPostParam("imageId");
			if(!isset($serverId)){
				$this->app->setOutput("Error", "Image ID is missing!");
				return;
			}
			$opt = array('id' => $imageId);
			$image = $this->libClass->getImage($opt);
			$image->retrieve();
			$this->app->setOutput("MyImage", $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);
		}
	}
	
	/**
	* Create server.
	*
	* @return void
	*/ 
	public function createServer()
	{
		try{
			$name = $this->app->getPostParam("name");
			$imageId = $this->app->getPostParam("imageId");
			$flavorId = $this->app->getPostParam("flavorId");
			if(!isset($name) || !isset($imageId) || !isset($flavorId)){
				$this->app->setOutput("Error", "Server name OR image ID OR flavor ID is missing.");
				return;
			}
			$opt = array('name' => $name, 'imageId' => $imageId, 'flavorId' => $flavorId);
			$server = $this->libClass->createServer($opt);
		}
		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 server
	*
	* @return void
	*/
	public function updateServer()
	{
		try{
			$serverId = $this->app->getPostParam("serverId");
			$newName = $this->app->getPostParam("newName");
			$newIpv4 = $this->app->getPostParam("newIpv4");
			$newIpv6 = $this->app->getPostParam("newIpv6");
			if(!isset($serverId)|| !(isset($newName) || isset($newIpv4) || isset($newIpv6)) ){
				$this->app->setOutput("Error", "You'll have to provide server ID and the new attribute(IP(v4/v6)/Name) you desire to update!");
				return;
			}
			$opt = array('id' => $serverId);
			$server = $this->libClass->getServer($opt);
			if (isset($newName)){
				if(isset($newIpv4)){
					if(isset($newIpv6)){
						$attr = array('name' => $newName, 'accessIPv4' => $newIPv4, 'accessIPv6' => $newIpv6); 
					}
					else $attr = array('name' => $newName, 'accessIPv4' => $newIPv4); 
				}
				else $attr = array('name' => $newName); 
			}			
			$server->update($attr);
			$this->app->setOutput("Success", $serverId." has been updated successfully.");
		}
		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);
		}
	}
	
	/**
	* Delete a server
	*
	* @return void
	*/
	public function deleteServer()
	{
		try{
			$serverId = $this->app->getPostParam("serverId");
			if(!isset($serverId)){
				$this->app->setOutput("Error", "Server ID is missing!");
				return;
			}
			$opt = array('id' => $serverId);
			$server = $this->libClass->getServer($opt);
			$server->delete();
			$this->app->setOutput("Success", $serverId." has been deleted successfully.");
		}
		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);
		}
	}
	
	/**
	* Change the password of a server
	*
	* @return void
	*/
	public function changePassword()
	{
		try{
			$serverId = $this->app->getPostParam("serverId");
			$password = $this->app->getPostParam("newPassword");
			if(!isset($serverId) || !isset($password)){
				$this->app->setOutput("Error", "Server ID or new password missing.");
				return;
			}
			$opt = array('id' => $serverId);
			$server = $this->libClass->getServer($opt);
			$server->changePassword($password);	
			$this->app->setOutput("Success", "Password for ".$serverId." has been updated successfully.");
		}
		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);
		}
	}
	
	/**
	* Reboot a server
	*
	* @return void
	*/
	public function reboot()
	{
		try{
			$serverId = $this->app->getPostParam("serverId");
			if(!isset($serverId)){
				$this->app->setOutput("Error", "Server ID is missing!");
				return;
			}
			$opt = array('id' => $serverId);
			$server = $this->libClass->getServer($opt);
			$server->reboot();
			$this->app->setOutput("Success", $serverId." has been deleted successfully.");
		}
		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);
		}
	}
	
	/**
	* Rebuild a server
	*
	* @return void
	*/
	public function rebuild()
	{
		$serverId = $this->app->getPostParam("serverId");
		$imageId = $this->app->getPostParam("imageId");
		$newName = $this->app->getPostParam("newName");
		$adminPass = $this->app->getPostParam("adminPass");
		if(!isset($serverId)|| !isset($imageId) || isset($newName) || isset($adminPass)) {
			$this->app->setOutput("Error", "You'll have to provide server ID and the new image, name and admin password!");
			return;
			try{
				$serverId = $this->app->getPostParam("serverId");
				$imageId = $this->app->getPostParam("imageId");
				$newName = $this->app->getPostParam("newName");
				$adminPass = $this->app->getPostParam("adminPass");
				if(!isset($serverId)|| !isset($imageId) || isset($newName) || isset($adminPass)){
					$this->app->setOutput("Error", "You'll have to provide server ID and the new image, name and admin password!");
					return;
				}
				$opt = array('id' => $serverId);
				$server = $this->libClass->getServer($opt);
				$attr = array('imageId' => $imageId, 'name' => $newName, 'adminPass' => $adminPass); 
				$server->rebuild($attr);
				$this->app->setOutput("Success", $serverId." has been rebuilt successfully with the new 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);
			}
		}
	}
	
	/**
	* Resize a server
	*
	* A call to this method has to be followed by either confirmResize or revertResize
	*
	* @return void
	*/
	public function resize()
	{
		try{
			$serverId = $this->app->getPostParam("serverId");
			$newFlavorId = $this->app->getPostParam("newFlavorId");
			if(!isset($serverId)|| !isset($flavorId)){
				$this->app->setOutput("Error", "You'll have to provide server ID and the new flavor ID!");
				return;
			}
			$opt = array('id' => $serverId);
			$server = $this->libClass->getServer($opt);
			$server->resize($newFlavorId);
		}
		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);
		}
	}
	
	/**
	* Confirm resize operation on a server
	*
	* @return void
	*/
	public function confirmResize()
	{
		try{
			$serverId = $this->app->getPostParam("serverId");
			if(!isset($serverId)){
				$this->app->setOutput("Error", "Server ID is missing!");
				return;
			}
			$opt = array('id' => $serverId);
			$server = $this->libClass->getServer($opt);
			$server->confirmResize();
			$this->app->setOutput("Success", $serverId." has been resized successfully as the new flavor.");
		}
		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);
		}
	}
	
	/**
	* Revert resize operation on a server
	*
	* @return void
	*/
	public function revertResize()
	{
		try{
			$serverId = $this->app->getPostParam("serverId");
			if(!isset($serverId)){
				$this->app->setOutput("Error", "Server ID is missing!");
				return;
			}
			$opt = array('id' => $serverId);
			$server = $this->libClass->getServer($opt);
			$server->revertResize();
			$this->app->setOutput("Success", $serverId." : resize operation has been reverted to the old flavor.");
		}
		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 private and public addresses of a server
	*
	* @return void
	*/
	public function listAddresses()
	{
		try{
			$serverId = $this->app->getPostParam("serverId");
			if(!isset($serverId)){
				$this->app->setOutput("Error", "Server ID is missing!");
				return;
			}
			$opt = array('id' => $serverId);
			$server = $this->libClass->getServer($opt);
			$addresses = $server->listAddresses();
			$this->app->setOutput("Addresses", $addresses);
		}
		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);
		}
	}
}