package agent;

import java.util.Hashtable;

import jade.core.*;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.DFService;
import jade.domain.FIPAException;
import reservationManager.ReservationManager;

/**
 * This class implements the Resource Manager agent,
 * who can negotiate about his resource.
 * 
 * The agent holds two data structures of state, in order to
 * be able to communicate with the askers, about the reservations
 * they did before.
 * 
 * One is RESERVATOR, which handle one reservation:
 * 	* checks if there is enough resource to reserve
 *  * creates the reservation, and returns ID
 *  * allows the reservation to be either renewed
 *  * retracted (all the resources are freed)
 *  * commite (the resources are used, and then freed)
 * 
 * The other data structure is ASKERS,
 * every negotiation has an entry here, holding the Asker name
 * the last prices of both sides, number of exchanged proposals...
 * This one is used in order to be able to say the next price
 * in the negotiation process
 * 
 * @author ShmulyanAdmin
 */
public class ResourceManager extends Agent {
	private ReservationManager reservator = null;
	private Hashtable askersDB = new Hashtable();
	private int minPricePerUnit=100;
	public int managedResorcesAmount=1000;
	
	public ResourceManager(){
		super();
		//these are the defaulkt values for the amount of the resource we have
		//and for the minimal price
		//different values can be given when starting the agent
		
		reservator = new ReservationManager(managedResorcesAmount);
	}
	
	protected void setup() {
		Object[] args = getArguments();
		String resourceName= "Dummy Resource";
		try{
			managedResorcesAmount = Integer.parseInt((String) args[0]); 
			this.reservator = new ReservationManager(managedResorcesAmount);
			this.minPricePerUnit = Integer.parseInt((String) args[1]);
			resourceName = (String)args[2];
		}catch (Exception e){
			System.out.println("Couldnt retrieve params, using the default values");
			System.out.println("The format that should be given for jade.Boot is:");
			System.out.println("agent.ResourceManager(ResorcesAmount minPricePerUnit resourceName)");
			System.out.println("for example: agent.ResourceManager(1000 100 balls)");
		}
		System.out.println("We have "+reservator.getAvailableResource()+" units of "+ resourceName+".");
		System.out.println("Minimal accepted price per unit is "+minPricePerUnit);
		
		DFAgentDescription dfd = new DFAgentDescription();
		ServiceDescription sd = new ServiceDescription();
		sd.setType("ResourceManager");
		sd.setName(getName());
		sd.setOwnership(resourceName);
		dfd.setName(getAID());
		dfd.addServices(sd);
		
		
		//dfd.addServices(new ServiceDescription())
		try {
			DFService.register(this, dfd);
		} catch (FIPAException e) {
			System.err.println(getLocalName()
					+ " registration with DF unsucceeded. Reason: "
					+ e.getMessage());
			doDelete();
		}
		
		
		addBehaviour(new NegotiationBehaviour(this));
	} 
	
	/**
	 * Returns the internal instance of the class that manages all the reservations
	 * @return internal instance of the class that manages all the reservations
	 */
	public ReservationManager getReservator(){
		return this.reservator;
	}
	
	/**
	 * Returns the minimal price per unit of the resource 
	 * that we will accept
	 * @return minimal price per unit of the resource
	 */
	public int getMinPricePerUnit(){
		return this.minPricePerUnit;
	}
	
	/**
	 * returns the dict that contains all the info about each asker
	 * @return the dict that contains all the info about each asker
	 */
	public Hashtable getAskersDB(){
		return this.askersDB;
	}
};

class AskerInfo {
	public AID asker;
	public int time;
	public int reservationId;
	public int myLastPrice;
	public int hisLastPrice=-1;
	public int myNumProposals=1;
	
	public AskerInfo(AID asker, int reservationId,int time, int myLastPrice){
		this.myLastPrice = myLastPrice;
		this.asker = asker;
		this.time = time;
		this.reservationId = reservationId;
	}
}

