package interfacing;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import java.text.SimpleDateFormat;
import java.util.GregorianCalendar;
import javax.swing.*;

/**
 * This JPanel is responsible for viewing information about every job in the
 * system. It views the following: "ID", "Secondary ID", "Job Class", "Server",
 * "Date Submitted", "Date Sent" , "Date Started", "Date Done", "Status" and
 * "Timeout status" This class implements mapping.data.JobsTableListener.
 * 
 * @author Majd Kokaly
 * 
 */
public class JobsTableJPanel extends JPanel implements mapping.data.JobsTableListener, MouseListener {

	/**
	 * The serialVersionUID is used to universally identify this version of this
	 * class.
	 */
	private static final long serialVersionUID = -3722479581330212830L;

	/**
	 * This is main frame containing all the GUI component. A reference is
	 * needed to be able to access the Mapper object and its data.
	 */
	private MainFrame frame;

	/**
	 * This table is not editable
	 */
	private NonEditableTableModel tableModel;

	/**
	 * The JTable object responsible for viewing the data in tabular way
	 */
	private JTable jTable;

	/**
	 * The labels of the header row.
	 */
	// 0 1 2 3 4 5 6 7 8 9
	private String[] columnNames = { "ID", "Secondary ID", "Job Class", "Server", "Date Submitted", "Date Sent",
			"Date Started", "Date Done", "Status", "T/O" };

	/**
	 * A scrollPane for the JTable
	 */
	private JScrollPane scrollPane;

	/**
	 * The formatter responsible for how the dates should be viewed
	 */
	private SimpleDateFormat formatter;

	/**
	 * The default constructor. It initializes and lays the GUI objects.
	 * 
	 * @param frame
	 *            this is the MainFrame object that contains this JPanel
	 */
	public JobsTableJPanel(MainFrame frame) {
		this.frame = frame;

		formatter = new SimpleDateFormat("dd/MM/yy 'at' HH:mm:ss");
		jTable = new JTable();
		scrollPane = new JScrollPane();
		fillJTable();
		scrollPane.setViewportView(jTable);
		this.setLayout(new BorderLayout());
		this.add(scrollPane);

		jTable.addMouseListener(this);

		// Resizing the columns
		jTable.getColumnModel().getColumn(0).setPreferredWidth(40);
		jTable.getColumnModel().getColumn(1).setPreferredWidth(80);
		jTable.getColumnModel().getColumn(2).setPreferredWidth(60);
		jTable.getColumnModel().getColumn(3).setPreferredWidth(100);
		jTable.getColumnModel().getColumn(4).setPreferredWidth(150);
		jTable.getColumnModel().getColumn(5).setPreferredWidth(150);
		jTable.getColumnModel().getColumn(6).setPreferredWidth(150);
		jTable.getColumnModel().getColumn(7).setPreferredWidth(150);
		jTable.getColumnModel().getColumn(8).setPreferredWidth(50);
		jTable.getColumnModel().getColumn(9).setPreferredWidth(40);
		jTable.setGridColor(Color.GRAY);
	}

	/**
	 * This method initializes the JTable with the entries from JobsTable from
	 * the mapper of this object's MainFrame object
	 */
	public void fillJTable() {
		GregorianCalendar dateStarted, dateDone;
		String dateStartedString, dateDoneString, timedOut;
		tableModel = new NonEditableTableModel(columnNames, 0);
		jTable.setModel(tableModel);

		for (long i = 0; i < this.frame.getMapper().getJobsTable().size(); i++) {
			dateStarted = this.frame.getMapper().getJobsTable().getJobTimeStarted(i + 1);
			if (dateStarted == null) {
				dateStartedString = "";
			} else
				dateStartedString = formatter.format(dateStarted.getTime());

			dateDone = this.frame.getMapper().getJobsTable().getJobTimeDone(i + 1);
			if (dateDone == null) {
				dateDoneString = "";
			} else
				dateDoneString = formatter.format(dateDone.getTime());

			if (this.frame.getMapper().getJobsTable().getJobIsTimedOut(i + 1)) {
				timedOut = "Yes";
			} else
				timedOut = "No";
			String[] s = {
					this.frame.getMapper().getJobsTable().getJobIndex(i + 1) + "",
					this.frame.getMapper().getJobsTable().getJobSecondaryID(i + 1) + "",
					this.frame.getMapper().getJobsTable().getJobClassID(i + 1) + "",
					this.frame.getMapper().getJobsTable().getJobServer(i + 1).getIndex() + "",
					formatter.format(this.frame.getMapper().getJobsTable().getJobTimeSubmitted(i + 1).getTime()),
					dateStartedString, dateDoneString, this.frame.getMapper().getJobsTable().getJobStatus(i + 1) + "",
					timedOut };

			tableModel.addRow(s);
		}

	}

	/**
	 * This method is invoked by the JobsTable object when a new job is added.
	 * 
	 * @see mapping.data.JobsTableListener
	 */
	public void jobHasBeenAdded(long jobID, long jobSecondaryID, int jobClassID, String serverName,
			GregorianCalendar timeSubmitted, GregorianCalendar timeSent, GregorianCalendar timeStarted,
			GregorianCalendar timeDone, String status, boolean timedOut) {

		String timeSentString = "", timeStartedString = "", timeDoneString = "";
		if (timeSent != null)
			timeSentString = formatter.format(timeSent.getTime());
		if (timeStarted != null)
			timeStartedString = formatter.format(timeStarted.getTime());
		if (timeDone != null)
			timeDoneString = formatter.format(timeDone.getTime());
		String timedOutString = "No";
		if (timedOut) {
			timedOutString = "Yes";
		}

		String[] s = { jobID + "", jobSecondaryID + "", jobClassID + "", serverName,
				formatter.format(timeSubmitted.getTime()), timeSentString, timeStartedString, timeDoneString, status,
				timedOutString };
		tableModel.addRow(s);
		this.repaint();
	}

	/**
	 * This method is invoked by the JobsTable object when a job's secondary id
	 * is changed.
	 * 
	 * @see mapping.data.JobsTableListener
	 */
	public void secondaryIDHasBeenChanged(long jobID, long jobSecondayID) {
		tableModel.setValueAt(jobSecondayID, (int) jobID - 1, 1);
	}

	/**
	 * This method is invoked by the JobsTable object when a job's class id is
	 * changed.
	 * 
	 * @see mapping.data.JobsTableListener
	 */
	public void jobClassIDHasBeenChanged(long jobID, int jobClassId) {
		tableModel.setValueAt(jobClassId, (int) jobID - 1, 2);

	}

	/**
	 * This method is invoked by the JobsTable object when a job's server name
	 * is changed. This should not occur
	 * 
	 * @see mapping.data.JobsTableListener
	 */
	public void serverNameHasBeenChanged(long jobID, String serverName) {}
	
	/**
	 * This method is invoked by the JobsTable object when a job's server id
	 * is changed.
	 * 
	 * @see mapping.data.JobsTableListener
	 */
	public void serverIDHasBeenChanged(long jobID, int serverID) {
		tableModel.setValueAt(serverID, (int) jobID - 1, 3);
	}

	/**
	 * This method is invoked by the JobsTable object when a job's submission
	 * time changed.
	 * 
	 * @see mapping.data.JobsTableListener
	 */
	public void timeSubmittedHasBeenChanged(long jobID, GregorianCalendar timeSubmitted) {
		tableModel.setValueAt(formatter.format(timeSubmitted.getTime()), (int) jobID - 1, 4);
	}

	/**
	 * This method is invoked by the JobsTable object when a job's sending time
	 * is changed.
	 * 
	 * @see mapping.data.JobsTableListener
	 */
	public void timeSentHasBeenChanged(long jobID, GregorianCalendar timeSent) {
		tableModel.setValueAt(formatter.format(timeSent.getTime()), (int) jobID - 1, 5);

	}

	/**
	 * This method is invoked by the JobsTable object when a job's start time is
	 * is changed.
	 * 
	 * @see mapping.data.JobsTableListener
	 */
	public void timeStartedHasBeenChanged(long jobID, GregorianCalendar timeStarted) {
		tableModel.setValueAt(formatter.format(timeStarted.getTime()), (int) jobID - 1, 6);

	}

	/**
	 * This method is invoked by the JobsTable object when a job's completion
	 * time is changed.
	 * 
	 * @see mapping.data.JobsTableListener
	 */
	public void timeDoneHasBeenChanged(long jobID, GregorianCalendar timeDone) {
		tableModel.setValueAt(formatter.format(timeDone.getTime()), (int) jobID - 1, 7);

	}

	/**
	 * This method is invoked by the JobsTable object when a job's status has
	 * been changed.
	 * 
	 * @see mapping.data.JobsTableListener
	 */
	public void statusHasBeenChanged(long jobID, String status) {
		tableModel.setValueAt(status, (int) jobID - 1, 8);
	}

	/**
	 * This method is invoked by the JobsTable object when a job's time-out
	 * status has been changed
	 * 
	 * @see mapping.data.JobsTableListener
	 */
	public void timedOutStatusChanged(long jobID, boolean timedOut) {
		if (timedOut) {
			tableModel.setValueAt("Yes", (int) jobID - 1, 9);
		} else
			tableModel.setValueAt("No", (int) jobID - 1, 9);
	}

	/**
	 * This method handles the event of the user double clicking a job entry. It
	 * then shows info about that job.
	 */
	public void mouseClicked(MouseEvent e) {
		if (e.getClickCount() != 2)
			return;
		if (jTable.getSelectedRow() >= 0 && jTable.getSelectedRow() < this.frame.getMapper().getJobsTable().size()) {
			JOptionPane.showMessageDialog(this, "Server hostname is: "
					+ this.frame.getMapper().getJobsTable().getJobServer((long) jTable.getSelectedRow() + 1)
							.getHostName(), "Job", JOptionPane.INFORMATION_MESSAGE);

		}
	}

	public void mouseEntered(MouseEvent e) {

	}

	public void mouseExited(MouseEvent e) {

	}

	public void mousePressed(MouseEvent e) {

	}

	public void mouseReleased(MouseEvent e) {

	}

}
