/* This class defines a simulator for page replacement algorithms.
 * You can use any page replacement algorithm.
 * Any method of generating page references can be used. 
 */
public class Simulator {
    /* This class defines the history of page accesses. 
     * The pageString gives the page numbers in the order of reference.
     * The faultStgring tells whether a page fault was encountered for this reference. 
     * The numPageFaults gives the total number of page faults.
     * The numReferences gives the number of references in the pageString.
     */
    public class History {
	public int numPageFaults;
	public int numReferences;
	public int pageString[];
	public boolean faultString[];

	public History (int numReferences) {
	    pageString = new int[numReferences];
	    faultString = new boolean[numReferences];

	    for (int i=0; i<numReferences; i++) {
		pageString[i] = -1;
		faultString[i] = false;
	    }
	    numPageFaults++;
	}
	
	public void print() {
	    for (int i=0; i<pageString.length; i++) {
		System.out.println(pageString[i]+" "+faultString[i]);
	    }
	}
    }

    private int numReferences;  /* number of references to be generated. */
    private PageManager pageManager;  /* user defined page manager. */
    private ReferenceGenerator referenceGenerator; /* user defined reference generator. */
    private MemoryInterface memoryInterface; /* simulates main memory. */

    /* This constructor initializes the simultor. 
     */
    public Simulator (int numReferences, PageManager pageManager, ReferenceGenerator referenceGenerator, MemoryInterface  memoryInterface) {
	this.numReferences = numReferences;
	this.pageManager = pageManager;
	this.referenceGenerator = referenceGenerator;
	this.memoryInterface = memoryInterface;
    }

    /* This method runs the simutation.
     * The reference genrator is initialized seed 0.
     * It returns the history of the simulation.
     */
    public History simulate () {
	return simulate(0);
    }

    /* This method runs the simutation.
     * The reference generator is initialized with the given seed.
     * It returns the history of the simulation.
     */
    public History simulate (long seed) {
	History history = new History(numReferences);

	memoryInterface.reset();
	referenceGenerator.init(seed);

	for (int i=0; i<numReferences; i++) {
	    int page = referenceGenerator.nextReference();
	    
	    history.pageString[i] = page;
	    if (!memoryInterface.isMapped(page)) {
		pageManager.handlePageFault(page,memoryInterface);
		history.faultString[i] = true;
	    }
	    pageManager.handlePageReference(page, memoryInterface);
	}
	return history;
    }
}
    
