/*
 * JaamSim Discrete Event Simulation
 * Copyright (C) 2013 Ausenco Engineering Canada Inc.
 *
 * This program 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.
 *
 * This program 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.
 */
package com.jaamsim.ui;

import java.awt.Point;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;

import com.sandwell.JavaSimulation.Entity;
import com.sandwell.JavaSimulation3D.GUIFrame;

public class OutputBox extends FrameBox {
	private static OutputBox myInstance;
	private Entity currentEntity;
	OutputTableModel tableModel;

	private ArrayList<String> outputNames = new ArrayList<String>();
	private ArrayList<Boolean> rowIsClass = new ArrayList<Boolean>();

	public OutputBox() {
		super( "Output Viewer" );
		setDefaultCloseOperation(FrameBox.DISPOSE_ON_CLOSE);

		tableModel = new OutputTableModel();
		OutputTable table = new OutputTable(tableModel);
		JScrollPane scrollPane = new JScrollPane(table);

		getContentPane().add( scrollPane );

		table.getTableHeader().setFont(FrameBox.boldFont);
		table.getTableHeader().setReorderingAllowed(false);

		table.getColumnModel().getColumn(0).setHeaderValue("Output");
		table.getColumnModel().getColumn(1).setHeaderValue("Value");

		table.setDefaultRenderer(Object.class, colRenderer);

		setEntity(null);

		setLocation(GUIFrame.COL3_START, GUIFrame.LOWER_START);
		setSize(GUIFrame.COL3_WIDTH, GUIFrame.LOWER_HEIGHT);
	}

	/**
	 * Returns the only instance of the property box
	 */
	public synchronized static OutputBox getInstance() {
		if (myInstance == null)
			myInstance = new OutputBox();

		return myInstance;
	}

	@Override
	public void setEntity( Entity entity ) {
		currentEntity = entity;
		if (currentEntity == null) {
			setTitle("Output Viewer");
			outputNames.clear();
			rowIsClass.clear();
			return;
		}
		setTitle("Output Viewer - " + currentEntity.getInputName());

		// Build up the row list, leaving extra rows for entity names
		String[] tempNames = currentEntity.getSortedOutputNames();
		Class<?> currClass = null;

		outputNames = new ArrayList<String>();
		rowIsClass = new ArrayList<Boolean>();

		for (String name : tempNames) {
			Class<?> klass = currentEntity.getOutputDeclaringClass(name);
			if (currClass != klass) {
				// This is the first time we've seen this class, add a place holder row
				currClass = klass;
				outputNames.add(klass.getSimpleName());
				rowIsClass.add(true);
			}
			outputNames.add(name);
			rowIsClass.add(false);
		}
	}

	@Override
	public void updateValues(double simTime) {
		tableModel.simTime = simTime;
		tableModel.fireTableDataChanged();
	}

	private synchronized static void killInstance() {
		myInstance = null;
	}

	@Override
	public void dispose() {
		killInstance();
		super.dispose();
	}

private class OutputTable extends JTable {
	public OutputTable(TableModel model) {
		super(model);
	}

	@Override
	public String getToolTipText(MouseEvent event) {
		Point p = event.getPoint();
		int row = rowAtPoint(p);
		if (row >= outputNames.size() || currentEntity == null || rowIsClass.get(row)) {
			return null;
		}

		String outputName = outputNames.get(row);

		StringBuilder build = new StringBuilder();
		build.append("<HTML>");
		build.append("<b>Name:</b>  ");
		build.append(outputName);
		build.append("<BR>");
		String desc = currentEntity.getOutputDescripion(outputName);
		if (!desc.isEmpty()) {
			build.append("<BR>");
			build.append("<b>Description:</b> ");
			for (String line : desc.split("\n", 0)) {
				// Replace all <> for html parsing
				String tempLine = line.replaceAll("&", "&amp;");
				tempLine = tempLine.replaceAll("<", "&lt;");
				tempLine = tempLine.replaceAll(">", "&gt;");

				int len = 0;
				build.append("<BR>");
				// Break the line at 100-char boundaries
				for (String word : tempLine.split(" ", -1)) {
					build.append(word).append(" ");
					len += word.length() + 1;
					if (len > 100) {
						build.append("<BR>");
						len = 0;
					}
				}
			}
		}
		return build.toString();
	}

	@Override
	public void doLayout() {
		FrameBox.fitTableToLastColumn(this);
	}
}

private class OutputTableModel extends AbstractTableModel {
	double simTime = 0.0d;
	@Override
	public int getColumnCount() {
		return 2;
	}

	@Override
	public int getRowCount() {
		return outputNames.size();
	}

	@Override
	public Object getValueAt(int row, int col) {

		switch (col) {
		case 0:
			if (rowIsClass.get(row)) {
				return String.format("<HTML><B>%s</B></HTML>", outputNames.get(row));
			}
			return String.format("    %s", outputNames.get(row));
		case 1:
			if (rowIsClass.get(row)) {
				return "";
			}
			return currentEntity.getOutputAsString(outputNames.get(row), simTime);
		default:
			assert false;
			return null;
		}
	}

	@Override
	public boolean isCellEditable(int rowIndex, int columnIndex) {
		return false;
	}
}

}

@@ -1614,136 +1614,8 @@
 );%0A%0A
-%09%09table.getColumnModel().getColumn(0).setHeaderValue(%22Output%22);%0A%09%09table.getColumnModel().getColumn(1).setHeaderValue(%22Value%22);%0A%0A
 %09%09ta
@@ -4610,24 +4610,180 @@
 turn 2;%0A%09%7D%0A%0A
+%09@Override%0A%09public String getColumnName(int column) %7B%0A%09%09switch (column) %7B%0A%09%09case 0: return %22Output%22;%0A%09%09case 1: return %22Value%22;%0A%09%09%7D%0A%0A%09%09return %22Unknown%22;%0A%09%7D%0A%0A
 %09@Override%0A%09

move column names into TabelModel in OutputBox like other viewers do