/*
 * ARISTOTLE UNIVERSITY OF THESSALONIKI
 * Copyright (C) 2015
 * Aristotle University of Thessaloniki
 * Department of Electrical & Computer Engineering
 * Division of Electronics & Computer Engineering
 * Intelligent Systems & Software Engineering Lab
 *
 * Project             : eticsbte
 * WorkFile            : 
 * Compiler            : 
 * File Description    : 
 * Document Description: 
* Related Documents	   : 
* Note				   : 
* Programmer		   : RESTful MDE Engine created by Christoforos Zolotas
* Contact			   : christopherzolotas@issel.ee.auth.gr
*/


package eu.fp7.scase.eticsbte.virtualmachine;

import java.util.List;
import java.util.Arrays;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;


import eu.fp7.scase.eticsbte.utilities.HypermediaLink;
import eu.fp7.scase.eticsbte.utilities.HibernateController;
import eu.fp7.scase.eticsbte.virtualenvironment.JavavirtualEnvironmentModel;

/* This class processes PUT requests for virtualMachine resources and creates the hypermedia to be returned to the client*/

public class PutvirtualMachineHandler{


    private HibernateController oHibernateController;
    private UriInfo oApplicationUri; //Standard datatype that holds information on the URI info of this request
	private String strResourcePath; //relative path to the current resource
    private JavavirtualMachineModel oJavavirtualMachineModel;
    private JavavirtualEnvironmentModel oJavavirtualEnvironmentModel;
    private String strOptionalUpdateRelations;
    private String strOptionalUpdateParent;
    private String strOptionalRelationName;
    private Integer iOptionalResourceId;
    private String strOptionalAddRelation;
    private final List<String> listOfParentResources = Arrays.asList("virtualEnvironment");
    private final List<String> listOfChildrenResources = Arrays.asList("software");

    public PutvirtualMachineHandler(int virtualEnvironmentId, int virtualMachineId, JavavirtualMachineModel oJavavirtualMachineModel, UriInfo oApplicationUri, String strOptionalUpdateRelations, String strOptionalUpdateParent, String strOptionalRelationName, String strOptionalAddRelation, Integer iOptionalResourceId){
        this.oJavavirtualMachineModel = oJavavirtualMachineModel;
        this.oJavavirtualMachineModel.setvirtualMachineId(virtualMachineId);
        this.oHibernateController = HibernateController.getHibernateControllerHandle();
        this.oApplicationUri = oApplicationUri;
		this.strResourcePath = calculateProperResourcePath();
        oJavavirtualEnvironmentModel = new JavavirtualEnvironmentModel();
        oJavavirtualEnvironmentModel.setvirtualEnvironmentId(virtualEnvironmentId);
        oJavavirtualMachineModel.getSetOfParentJavavirtualEnvironmentModel().add(this.oJavavirtualEnvironmentModel);
        this.strOptionalUpdateRelations = strOptionalUpdateRelations;
        System.out.println(this.strOptionalUpdateRelations);
        this.strOptionalUpdateParent = strOptionalUpdateParent;
        System.out.println(this.strOptionalUpdateParent);
        this.strOptionalRelationName = strOptionalRelationName;
        System.out.println(this.strOptionalRelationName);
        this.iOptionalResourceId = iOptionalResourceId;
        System.out.println(this.iOptionalResourceId);
        this.strOptionalAddRelation = strOptionalAddRelation;
        System.out.println(this.strOptionalAddRelation);
        
        if(this.strOptionalUpdateRelations != null && this.strOptionalUpdateRelations.equalsIgnoreCase("true")){
            checkRelationUpdateInfo();
        }
    }

    public String calculateProperResourcePath(){
        if(this.oApplicationUri.getPath().lastIndexOf('/') == this.oApplicationUri.getPath().length() - 1){
            return this.oApplicationUri.getPath().substring(0, this.oApplicationUri.getPath().length() - 1);
        }
        else{
            return this.oApplicationUri.getPath();
        }
    }

    private boolean hasParent(String strPossibleParentName){
        for(int i = 0; i < this.listOfParentResources.size(); i++){
            if(this.listOfParentResources.get(i).equalsIgnoreCase(strPossibleParentName)){
                return true;
            }
        }
        
        return false;
    }
    
    private boolean hasChild(String strPossibleChildName){
        for(int i = 0; i < this.listOfChildrenResources.size(); i++){
            if(this.listOfChildrenResources.get(i).equalsIgnoreCase(strPossibleChildName)){
                return true;
            }
        }
        
        return false;
    }
    
    private void checkRelationUpdateInfo(){
        
        //check if the request is about updating relations to parent resources
        if(this.strOptionalUpdateParent != null && this.strOptionalUpdateParent.equalsIgnoreCase("true")){
            //check if the request is to update relations to a valid parent resource
            if(this.strOptionalRelationName != null && hasParent(this.strOptionalRelationName)){
                if(this.strOptionalAddRelation != null && (this.strOptionalAddRelation.equalsIgnoreCase("true") || this.strOptionalAddRelation.equalsIgnoreCase("false"))
                   && (this.iOptionalResourceId != null && this.iOptionalResourceId > 0) ){
                    //then this is a valid request and should be processed
                    return;
                }
                else{ //else it is an invalid request
                    throw new WebApplicationException(Response.Status.BAD_REQUEST);
                }
            }
            else{ //else the selected parent resource is an invalid parent and this is a bad request
                throw new WebApplicationException(Response.Status.BAD_REQUEST);
            }
        }
        //of if it is about updating relations to children resources
        else if(this.strOptionalUpdateParent != null && this.strOptionalUpdateParent.equalsIgnoreCase("false")){
            //check if the request is to update relations to a valid child resource
            if(this.strOptionalRelationName != null && hasChild(this.strOptionalRelationName)){
                if(this.strOptionalAddRelation != null && (this.strOptionalAddRelation.equalsIgnoreCase("true") || this.strOptionalAddRelation.equalsIgnoreCase("false"))
                   && (this.iOptionalResourceId != null && this.iOptionalResourceId > 0) ){
                    //then this is a valid request and should be processed
                    return;
                }
                else{ //else it is an invalid request
                    throw new WebApplicationException(Response.Status.BAD_REQUEST);
                }
            }
            else{ //else the selected parent resource is an invalid parent and this is a bad request
                throw new WebApplicationException(Response.Status.BAD_REQUEST);
            }
        }
        else{ //otherwise this is a bad request
            throw new WebApplicationException(Response.Status.BAD_REQUEST);
        }
    }


    public JavavirtualMachineModel putJavavirtualMachineModel(){


		return createHypermedia(oHibernateController.putvirtualMachine(oJavavirtualMachineModel, this.strOptionalUpdateRelations, this.strOptionalUpdateParent, this.strOptionalRelationName, this.strOptionalAddRelation, this.iOptionalResourceId));
    }


    /* This function produces hypermedia links to be sent to the client so as it will be able to forward the application state in a valid way.*/
    public JavavirtualMachineModel createHypermedia(JavavirtualMachineModel oJavavirtualMachineModel){

		        /* Create hypermedia links towards this specific Resource resource. These can be GET, PUT and/or delete depending on what was specified in the service CIM.*/
		        oJavavirtualMachineModel.getlinklist().add(new HypermediaLink(String.format("%s%s", oApplicationUri.getBaseUri(), this.strResourcePath), "Get the virtualMachine", "GET", "Sibling"));
		        oJavavirtualMachineModel.getlinklist().add(new HypermediaLink(String.format("%s%s", oApplicationUri.getBaseUri(), this.strResourcePath), "Update the virtualMachine", "PUT", "Sibling"));
		        oJavavirtualMachineModel.getlinklist().add(new HypermediaLink(String.format("%s%s", oApplicationUri.getBaseUri(), this.strResourcePath), "Delete the virtualMachine", "DELETE", "Sibling"));
		
		        /* Calculate the relative path towards any related resources of this one. Then add each new hypermedia link with that relative path to the hypermedia linklist to be sent back to client.*/
		        String oRelativePath;
		        oRelativePath = this.strResourcePath.substring(this.strResourcePath.indexOf("/virtualMachine") + 1);
		        oJavavirtualMachineModel.getlinklist().add(new HypermediaLink(String.format("%s%s/%s", oApplicationUri.getBaseUri(), oRelativePath, "software"), "Get all the softwares of this virtualMachine", "GET", "Child"));
		        oJavavirtualMachineModel.getlinklist().add(new HypermediaLink(String.format("%s%s/%s", oApplicationUri.getBaseUri(), oRelativePath, "software"), "Create a new software for this virtualMachine", "POST", "Child"));
		
		        /* Finally, truncate the current URI so as to point to the resource manager of which this resource is related.
		        Then create the hypermedia links towards the parent resources.*/
		        int iLastSlashIndex = String.format("%s%s", oApplicationUri.getBaseUri(), this.strResourcePath).lastIndexOf("/");
		        oJavavirtualMachineModel.getlinklist().add(new HypermediaLink(String.format("%s%s", oApplicationUri.getBaseUri(), this.strResourcePath).substring(0, iLastSlashIndex), "Create a new virtualMachine", "POST", "Parent"));
		        oJavavirtualMachineModel.getlinklist().add(new HypermediaLink(String.format("%s%s", oApplicationUri.getBaseUri(), this.strResourcePath).substring(0, iLastSlashIndex), "Get all virtualMachines of this virtualEnvironment", "GET", "Parent"));
		 

        return oJavavirtualMachineModel;
    }
}
