/** 
 * @author YourAndrewIDHere
 * You should fill in the stub for this code file.  The
 * arguments will be given to you 
 */

import java.io.*;
import java.util.*;

public class ProbModelDriver {
	
	public ProbNode[] network;
	public double prob;
	public int initNode;
	public final int numberOfTrials = 10000;
	
	public ProbModelDriver(int size, double prob)
	{
		this.prob = prob;
		this.initNode = -1;
		this.network = new ProbNode[size];
		
		for(int i = 0; i < size; i++)
		{
			this.network[i] = new ProbNode(i);
		}
	}
	
	public void resetNetwork()
	{
		for(int i = 0; i < this.network.length; i++)
		{
			this.network[i].user = false;
		}
	}
	
	public void runSimulation(int initialNode)
	{
		this.initNode = initialNode;
		ArrayList<ProbNode> queue = new ArrayList<ProbNode>();
		ProbNode n = network[initialNode];
		n.user = true;
		queue.add(n);
		
		while(queue.size() > 0)
		{
			n = queue.get(0);
			queue.remove(0);
			ArrayList<ProbNode> tempList = n.convertNeighbor(this.prob);
			while(tempList.size() > 0)
			{
				ProbNode temp = tempList.get(0);
				tempList.remove(0);
				temp.user = true;
				queue.add(temp);
			}
		}
	}
	
	public void printResult()
	{
		System.out.println("initial node: " + this.initNode + "  \t" + "conversion rate = " + this.convertRate());
	}
	
	public double convertRate()
	{
		int count = 0;
		for(int i = 0; i < this.network.length; i++)
			if(this.network[i].user)
				count++;
		return (double) count / (double) this.network.length;
	}

	/**
	 * The first argument is the model filename
	 * The second argument should be the value of p, as an ASCII string
	 * The third argument should be the NodeID of the initial product user
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		if(args.length < 3)
		{
			System.out.println("Usage: ProbModelDriver netDefFilename pValue initialNode (-test)");
			return;
		}
		
		String networkFilename = args[0];
		double successProb = Double.parseDouble(args[1]);
		int    startNode = Integer.parseInt(args[2]);
		

		// Put any code here that you need to initialize your network model
		FileInputStream fin;
		DataInputStream data;
		fin = new FileInputStream(networkFilename);
		data = new DataInputStream(fin);
		
		String s = data.readLine();
		int size = Integer.parseInt(s);
		ProbModelDriver probModel = new ProbModelDriver(size, successProb);
		
		while(data.available() > 0)
		{
			s = data.readLine();
			int spaceIndex = s.indexOf(' ');
			int nodeOne = Integer.parseInt(s.substring(0,spaceIndex));
			int nodeTwo = Integer.parseInt(s.substring(spaceIndex + 1));
			
			probModel.network[nodeOne].addNeighbor(probModel.network[nodeTwo]);	// adding edge between two nodes
		}
		// creation of the network is done
		
		// DO NOT REMOVE THE FOLLOWING CODE.
		if(args.length == 4 && args[3].toLowerCase().equals("-test"))
		{
			// Put your code to simulate the network
			// here.  You should print out at the end
			// of the simulation all of the nodes which
			// are using the product.
			probModel.runSimulation(startNode);
			//probModel.printResult();
			for(int i = 0; i < probModel.network.length; i++)
			{
				if(probModel.network[i].user)
					System.out.print(i + " ");
			}
			
			//System.out.println("Put your output as specified in the assignment here.");
			return; // make sure that this return is called!
		}
		
		probModel.prob = 0.05;
		FileOutputStream fos; 
		DataOutputStream dos;
		File file= new File("probResult.xls");
	    fos = new FileOutputStream(file);
	    dos=new DataOutputStream(fos);
		ArrayList<double[]> dataArray = new ArrayList<double[]>(); // each index contains the simulation results from one probability
		for(;probModel.prob < 1;)
		{	
			System.out.println("Prob: " + probModel.prob);
			
			double[] tempArray = new double[probModel.network.length];
			for(int i = 0; i < probModel.network.length; i++)
			{
				double sum = 0;
				
				for(int j = 0; j < probModel.numberOfTrials; j++)
				{
					probModel.runSimulation(i);
					sum += probModel.convertRate();
					//probModel.printResult();
					probModel.resetNetwork();
				}
				sum /= (double)probModel.numberOfTrials;	// sum is now the average conversion rate
				tempArray[i] = sum;
				//dos.writeChars(probModel.initNode + "\t" + sum + "\n");
				//System.out.println("initial node: " + probModel.initNode + "  \t" + "conversion rate = " + sum);
			}
			dataArray.add(tempArray);
			//fos.close();
			probModel.prob += 0.05;
		}
		for(int i = 5; i < 100;)
		{
			dos.writeChars("\t" + i);
			i += 5;
		}
		dos.writeChars("\n");
		
		for(int i = 0; i < probModel.network.length; i++)
		{
			//double percent = (i + 1) * 0.05;
			String tempString = i + "";
			for(int j = 0; j < dataArray.size(); j++)
				tempString += "\t" + dataArray.get(j)[i];
			dos.writeChars(tempString + "\n");
		}
		fos.close();
		
		
		// You are free to do whatever you want here...
		// Bren suggests that you create some helper classes
		// to do the simulation and then run your simulations
		// on a variety of parameters in this space.
		System.out.println("This assignment rocks.");
	}

}

