/*
	Copyright 2011 Daniel Pletea

	This file is part of T-Nano.

	T-Nano is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	T-Nano is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with T-Nano.  If not, see <http://www.gnu.org/licenses/>.
 */

import java.awt.Color;
import java.awt.Component;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

/**
 * this class is created for creating a new gui for the simulation with all the
 * input scenarios
 * 
 * @author Daniel Pletea
 * 
 */
public class GuiSimulation extends Gui {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	// JComponents which are used to display the results
	private JTable table;
	private JScrollPane tableVerticalScroll;
	private JLabel messageLabel;
	private char messPoints;

	// the name of the circuit and the inputFile and the outputFile
	private String name;
	private String inputFile;
	private String outputFile;

	// a list with the names of the inputs
	private List<String> inputNames;

	// the number of the Inputs and the outputs
	private int nrInputs, nrOutputs;

	// ID of the simulation
	int ID;
	
	// this boolean variable is used for indicating if simulation is done
	private boolean end;

	public GuiSimulation(String name, int ID, List<String> outputs, List<String> inputs) {

		super();

		System.out.println(outputs.toString());
		System.out.println(inputs.toString());

		nrInputs = inputs.size();
		nrOutputs = outputs.size();

		// creating the array columns with the name
		// of the inputs and the outputs
		String[] columns = new String[outputs.size() + inputs.size()];
		for (int i = 0; i < columns.length; i++)
			if (i < inputs.size())
				columns[i] = inputs.get(i);
			else
				columns[i] = outputs.get(i - inputs.size());

		// counting the number of rows based on the number of the inputs
		// nrRows = 2^nrInputs
		int nrRows = 1;
		for (int i = 0; i < inputs.size(); i++)
			nrRows *= 2;

		Integer[][] rows = new Integer[nrRows][columns.length];
		inputNames = new ArrayList<String>();

		for (int i = 0; i < rows.length; i++) {
			int x = i;
			int y = nrRows / 2;
			String inName = "";
			for (int j = 0; j < nrInputs; j++) {
				rows[i][j] = x / y;
				inName += x / y;
				x = x % y;
				y = y / 2;
			}
			inputNames.add(inName);
		}

		System.out.println(inputNames.toString());
		System.out.println("Constructor simulation");

		table = new JTable(rows, columns);
		table.setBounds(150, 150, Main.fullSizeWidth - 260,
				Main.fullSizeHeight - 250);

		// makig differnce between the input columns and the output columns
		ColoredTableCellRenderer inputRenderer = new ColoredTableCellRenderer(
				Color.yellow);
		ColoredTableCellRenderer outputRenderer = new ColoredTableCellRenderer(
				Color.green);

		for (int i = 0; i < columns.length; i++)
			if (i < inputs.size())
				table.getColumnModel().getColumn(i)
						.setCellRenderer(inputRenderer);
			else
				table.getColumnModel().getColumn(i)
						.setCellRenderer(outputRenderer);

		// adding a scroll to the table
		tableVerticalScroll = new JScrollPane(table);
		tableVerticalScroll
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
		tableVerticalScroll
			.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
		tableVerticalScroll.setBounds(150, 150, Main.fullSizeWidth - 260,
				Main.fullSizeHeight - 250);
		this.add(tableVerticalScroll);
		
		messageLabel = Singleton.getInstance().createLabel("Simulating...", Main.fullSizeWidth / 2 - 75, 100, 150, 20, Color.WHITE, this);
		messPoints = 3;
		
		this.name = name;
		this.ID = ID;

		initSimulation();

		simulate();

		end = false;

		closeTaskItem.setEnabled(true);
	}

	/**
	 * class which extends DefaultTableRenderer
	 * 
	 * @author Daniel Pletea
	 *
	 */
	class ColoredTableCellRenderer extends DefaultTableCellRenderer {
		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		private Color color;

		public ColoredTableCellRenderer(Color color) {
			this.color = color;
		}

		public Component getTableCellRendererComponent(JTable table,
				Object value, boolean selected, boolean focused, int row,
				int column) {
			setEnabled(table == null || table.isEnabled()); // see question
															// above

			// setting the background with the color specified in the constructor
			setBackground(color);

			super.getTableCellRendererComponent(table, value, selected,
					focused, row, column);

			return this;
		}
	}

	private void simulate() {
		try {
			String nameOS = System.getProperty("os.name");

			String cmd = "sim.bat ";
			if (!nameOS.contains("Windows"))
				cmd = "./sim.sh ";
			cmd = cmd + inputFile + " " + outputFile + " " + outputFile + ID + ".prg";

			Runtime.getRuntime().exec(cmd);
		} catch (IOException e) {
			e.printStackTrace();
		}

		paint = true;
	}

	/**
	 * this function initializes the simulation
	 */
	private void initSimulation() {

		inputFile = name.substring(0, name.length() - 3) + ANALYZE_FILE;
		outputFile = name.substring(0, name.length() - 3) + SIMULATION_FILE;

		inputFile = Singleton.getInstance().tranformName(inputFile);
		outputFile = Singleton.getInstance().tranformName(outputFile);

		paint = true;
	}

	/**
	 * this functions ends the simulation
	 */
	private void endSimulation()
	{
		try {

			BufferedReader in = new BufferedReader(new FileReader(
					outputFile));
			
			Scanner scanner = new Scanner(in);

			int i = 0;
			int line = -1;
			while (scanner.hasNext()) {

				String string = scanner.next();
				
				if (i == 1)
					line = inputNames.indexOf(string);
				else if (i > 1 && i % 2 == 1) {
					
					// getting the value of the IO
					Scanner sc = new Scanner(string);
					int x = sc.nextInt();
					
					// put the value in the table
					table.setValueAt(new Integer(x), line, nrInputs
							+ (i / 2 - 1));
				}

				if (i == (nrOutputs * 2 + 2))
					i = -1;
				i++;
			}
				
			end = true;
			paint = true;
			
			in.close();					
			messageLabel.setText("Simulation results:");
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void update() {
		if (paint) {
			repaint();
			paint = false;
		}

		if (!end) {
			try {

				BufferedReader in = new BufferedReader(new FileReader(
						outputFile + ID + ".prg"));
				
				endSimulation();
				
				in.close();		
				
				String cmd = "rm " + outputFile + ID + ".prg";
				Runtime.getRuntime().exec(cmd);
				
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} 
			
			if(!end)
			{
				// sleep 1 second
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
				messPoints++;
				if(messPoints == 4) messPoints = 1;
				
				String message = "Simulating";
				for(int i = 0; i < messPoints; i++)
					message += ".";
				
				// modify the message for the user
				messageLabel.setText(message);
			}
		}
	}

}
