package edu.uprm.admg.nettraveler.sched;

import java.util.Random;

import edu.uprm.admg.nettraveler.plan.ExecutionSite;
import edu.uprm.admg.nettraveler.plan.Plan;
import edu.uprm.admg.nettraveler.type.MIInteger;
import edu.uprm.admg.util.hash.TableEntry;

public class RandomSched extends AbstractScheduler {
	/**
	 * 
	 */
	private static final long serialVersionUID = 6426086959265342501L;
	private Random rand = null;
	
	public RandomSched(int numPartitions) {
		super(numPartitions);
		this.rand = new Random();
	}

	@Override
	protected boolean localExist(ExecutionSite site) {
		return this.stable.hasEntryForSite(site);
	}

	@Override
	protected Plan localGetPlan(ExecutionSite site) {
		return this.stable.getEntry(site).getPlan();
	}

	@Override
	protected void localOTSched() throws SchedulerException{
		int bucketsRemains = this.numPartitions;
		int buckets;
		Plan plan = null;
		TableEntry entry = null;
		for(int i = 0; i<this.sites.length-1; i++){
			buckets = rand.nextInt(bucketsRemains);
			plan = this.assignBuckets(this.sites[i], buckets);
			entry = new TableEntry(this.sites[i],plan);
			this.stable.addEntry(entry);
			bucketsRemains-=buckets;
		}
		if(bucketsRemains>0){
			plan = this.assignBuckets(this.sites[this.sites.length-1], bucketsRemains);
			entry = new TableEntry(this.sites[this.sites.length-1],plan);
			this.stable.addEntry(entry);
		} 
	}

	@Override
	protected void localRTSched() throws SchedulerException{
		throw new SchedulerException("Runtime scheduling still unsupported");
	}

	@Override
	protected void localInit() throws SchedulerException {
		//nothing to do here at the moment
	}
	
	//	Check for the builded plan at the end 
	protected Plan assignBuckets(ExecutionSite site, int numBuckets) throws SchedulerException{
		int bucketSize = (numBuckets<this.stable.bucketsRemains())?numBuckets:this.stable.bucketsRemains();
		MIInteger[] buckets = new MIInteger[bucketSize];
		for(int i = 0;i<bucketSize;i++){
			buckets[i] = this.stable.removeFirst();
		}
		return this.setBuckets(site,buckets);
	}
}
