import java.util.Enumeration;
import java.util.Vector;

public class RecipeScheduler {
    int MAX_BLOCKS = 1000;

    RecipeBlock blocks[] = new RecipeBlock[MAX_BLOCKS];

    int maxBlock = 0;
    
    RecipePlan plan=null;

    public void addRecipe(Recipe r){
	RecipeBlock rb[] = r.getBlocks();
	System.arraycopy(rb, 0, blocks, maxBlock, r.size());
	maxBlock += r.size();
    }

    public void clear(){
	maxBlock = 0;
    }

    public void print() {
	if(plan == null){
	    System.out.println("No current plan");
	    return;
	}

	plan.print();
    }

    // Run the scheduling algorithm
    public void schedule(RecipePlan sofar) {
	System.out.println("Plan so far contains "+sofar.size()+" steps");
	if(sofar.size() >= maxBlock){
	    plan = sofar;
	    return;
	}

	System.out.println("---------- Plan so far:");
	sofar.print();

    BLOCKLOOP:
	for(int i = 0; i < maxBlock; i++){
	    System.out.println("Can I add "+blocks[i].name);
	    if(!sofar.contains(blocks[i])){
		// Would this break any prereqs,
		// wait constraints,
		// or resource requirements?

		// Check prereqs
		int earliest = 0;
		for(Enumeration e = blocks[i].prereqBlocks.elements();
		    e.hasMoreElements();){
		    RecipeBlock prereq = (RecipeBlock) e.nextElement();
		    if(!sofar.contains(prereq)){
			System.out.println("   Fails prereq constraint: "+prereq.name);
			continue BLOCKLOOP;
		    }
		    else{
			int eTime = sofar.endTimeOf(prereq);
			earliest = (eTime > earliest) ?
			    eTime:earliest;
		    }
		}
		// We now know the earliest this step could possibly happen
		System.out.println("Earliest it could occur given prereqs: "+earliest);

		// Check resource availability, specifically
		// find the soonest time after "earliest" that all
		// the required resources have a free slot of "maxDuration"
		int jump = 1;
		boolean good=false;
		for(int time = earliest; !good; time+=jump){
		    good = true;
		    earliest = time;
		    for(Enumeration rr = blocks[i].requiredResources.elements();
			rr.hasMoreElements();){
			String resource = (String) rr.nextElement();
			// Check if "resource" is available for blocks[i].maxDuration
			// right now
			System.out.println("Checking if "+resource+" is available at "+
					   time+" for "+blocks[i].maxDuration);
			int availableAt = sofar.whenAvailable(resource, 
							      time, 
							      blocks[i].maxDuration);
			if(availableAt > 0){
			    jump = (availableAt > jump) ? availableAt:jump;
			    good = false;
			}
		    }
		}
		// Now we know the earliest this step could happen, given
		// prereq's AND resource constraints, now we check if that's
		// too late
		System.out.println("Given resource constraints too: "+earliest);

		// Check wait constraints
		int endTime = earliest+blocks[i].maxDuration;
		if(!sofar.goodToTime(endTime, blocks[i])){
		    System.out.println("   Fails timing constraint");
		    continue BLOCKLOOP;
		}
		
		System.out.println("*** Added block "+blocks[i].name);
		sofar.addBlock(blocks[i], earliest);
		if(sofar.size() >= maxBlock){
		    plan = sofar;
		    return;
		}
		schedule(sofar);
		System.out.println("--- Hm, backing up, here's what I've got:");
		sofar.print();
	    }
	    else
		System.out.println("   Already planned for it");
	    
	}
	sofar.popBlock();
	System.out.println("Pop back...");
    }
}
