/** 
 * @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 DetermModelDriver {
	public DetermNode[] network;
	
	public DetermModelDriver(int size)
	{
		network = new DetermNode[size];
		for(int i = 0; i < size; i++)
		{
			this.network[i] = new DetermNode(i);
		}
	}
	
	public void runSimulation(ArrayList<Integer> initNodes)
	{
		for(int i=0; i < initNodes.size(); i++)
		{
			int node = initNodes.get(i).intValue();
			network[node].user = true;
		}
		
		boolean converted = true;
		while(converted)
		{
			converted = false;
			for(int i = 0; i < network.length; i++)
			{
				DetermNode d = network[i];
				if(!d.user) //if it's not a user
				{
					double sum = 0.0;
					for(int j = 0; j < network.length; j++)
						if(network[j].user)
							sum += d.bias[j];
					if(sum >= d.maxThresh)
					{
						d.user = true;
						converted = true;
					}
				}
			}
		}
	}
	
	public void resetNetwork()
	{
		for(int i=0; i < network.length; i++)
			network[i].user = false;
	}
	
	public String printResult()
	{
		String s = new String();
		for(int i = 0; i < network.length; i++)
		{
			if(network[i].user)
				s += i + " ";
		}
		return s;
	}
	
	public int countConvertedPeople()
	{
		int count = 0;
		for(int i = 0; i < network.length; i++)
		{
			if(network[i].user)
				count++;
		}
		return count;
	}
	/**
	 * The first argument is the model filename
	 * 
	 * All other arguments are integers which are the NodeIDs of states 
	 * initially active in the simulation.
	 * 
	 * The last argument is potentially a flag indicating that a test run
	 * will be performed.
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		if(args.length < 2)
		{
			System.out.println("Usage: DetermModelDriver Active1 (Active2) ... (ActiveN) (-test)");
			return;
		}
		
		String networkFilename = args[0];
		ArrayList<Integer> initialActiveNodes = new ArrayList<Integer>();
		
		FileInputStream fin;
		DataInputStream data;
		fin = new FileInputStream(networkFilename);
		data = new DataInputStream(fin);
		
		String s = data.readLine();
		int size = Integer.parseInt(s);
		DetermModelDriver determModel = new DetermModelDriver(size);
		
		while(data.available() > 0)
		{
			s = data.readLine();
			String[] tokens = s.split(" ");
			if(tokens.length == 2)
			{
				int i = Integer.parseInt(tokens[0]);
				double thresh = Double.parseDouble(tokens[1]);
				//System.out.print(i + " ");
				determModel.network[i].setThresh(thresh, determModel.network.length);
			}
			else if(tokens.length == 3)
			{
				int i = Integer.parseInt(tokens[0]);
				int j = Integer.parseInt(tokens[1]);
				double bias = Double.parseDouble(tokens[2]);
				determModel.network[i].bias[j] = bias;
			}
		}
		
		for(int i = 1; i < args.length; i++)
		{
			if(args[i].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.  
				determModel.runSimulation(initialActiveNodes);
				System.out.println(determModel.printResult());
				return; // make sure that this return is called!
			}
			
			initialActiveNodes.add(Integer.parseInt(args[i]));
		}
		
		ArrayList<Integer> bestSingleNode = new ArrayList<Integer>();
		int maxCount = 0;
		for(int i = 0; i < determModel.network.length; i++)
		{
			ArrayList<Integer> temp = new ArrayList<Integer>();
			temp.add(i);
			determModel.resetNetwork();
			determModel.runSimulation(temp);
			int count = determModel.countConvertedPeople();
			if(maxCount < count)
			{
				maxCount = count;
				bestSingleNode = temp;
			}
		}
		System.out.println(maxCount);
		
		ArrayList<Integer> bestDoubleNode = new ArrayList<Integer>();
		maxCount = 0;
		for(int i = 0; i < determModel.network.length; i++)
		{
			for(int j = i + 1; j < determModel.network.length; j++)
			{
				ArrayList<Integer> temp = new ArrayList<Integer>();
				temp.add(i);
				temp.add(j);
				determModel.resetNetwork();
				determModel.runSimulation(temp);
				int count = determModel.countConvertedPeople();
				if(maxCount < count)
				{
					maxCount = count;
					bestDoubleNode = temp;
				}
			}
		}
		System.out.println(maxCount);
		
		ArrayList<Integer> bestTripleNode = new ArrayList<Integer>();
		maxCount = 0;
		for(int i = 0; i < determModel.network.length; i++)
		{
			for(int j = i + 1; j < determModel.network.length; j++)
			{
				for(int k =  j + 1; k < determModel.network.length; k++)
				{
					ArrayList<Integer> temp = new ArrayList<Integer>();
					temp.add(i);
					temp.add(j);
					temp.add(k);
					determModel.resetNetwork();
					determModel.runSimulation(temp);
					int count = determModel.countConvertedPeople();
					if(maxCount < count)
					{
						maxCount = count;
						bestTripleNode = temp;
					}
				}
			}
		}
		System.out.println(maxCount);
		
		System.out.println("Best Single init Node is " + bestSingleNode.get(0).intValue());
		System.out.println("Best Double init Nodes are " + bestDoubleNode.get(0).intValue() + " " + bestDoubleNode.get(1).intValue());
		System.out.println("Best Triple init Nodes are " + bestTripleNode.get(0).intValue() + " " + bestTripleNode.get(1).intValue() + " " + bestTripleNode.get(2).intValue());
		
		// 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
		// here.
		System.out.println("This assignment rocks.");
	}

}

