/*
	A basic extension of the java.applet.Applet class
 */

import java.awt.*;
import java.applet.*;

public class Algorithm19 extends Applet
{
	private TableRepresentation table;
	private TableView view;
	private CPTableController controller;

	public void init()
	{
		// This code is automatically generated by Visual Cafe when you add
		// components to the visual environment. It instantiates and initializes
		// the components. To modify the code, only use code syntax that matches
		// what Visual Cafe can generate, or Visual Cafe may be unable to back
		// parse your Java file into its visual environment.
		//{{INIT_CONTROLS
		setLayout(null);
		setSize(493,411);
		header.setText("19. Constraint-propagation in a table representation");
		header.setAlignment(java.awt.Label.CENTER);
		add(header);
		header.setFont(new Font("Dialog", Font.PLAIN, 14));
		header.setBounds(0,0,480,24);
		activePanel.setLayout(null);
		add(activePanel);
		activePanel.setBounds(12,24,468,84);
		newTableButton.setLabel("New table");
		activePanel.add(newTableButton);
		newTableButton.setBackground(java.awt.Color.lightGray);
		newTableButton.setBounds(216,24,96,24);
		relationChoice.addItem("Point relations");
		relationChoice.addItem("Allen period relations");
		relationChoice.addItem("Symbolic period relations");
		relationChoice.addItem("Point period relations");
		relationChoice.addItem("Event relations");
		try {
			relationChoice.select(0);
		}
		catch (IllegalArgumentException e) { }
		activePanel.add(relationChoice);
		relationChoice.setBounds(300,0,168,25);
		numberOfElementsLabel.setText("Number of elements:");
		activePanel.add(numberOfElementsLabel);
		numberOfElementsLabel.setBounds(0,0,120,24);
		activePanel.add(numberOfElements);
		numberOfElements.setBounds(132,0,60,24);
		kindOfRelationLabel.setText("Kind of relation:");
		activePanel.add(kindOfRelationLabel);
		kindOfRelationLabel.setBounds(204,0,100,24);
		fillAllCellsButton.setLabel("Fill all cells randomly");
		activePanel.add(fillAllCellsButton);
		fillAllCellsButton.setBackground(java.awt.Color.lightGray);
		fillAllCellsButton.setBounds(324,24,144,24);
		fillOneCellButton.setLabel("Fill one cell at random");
		activePanel.add(fillOneCellButton);
		fillOneCellButton.setBackground(java.awt.Color.lightGray);
		fillOneCellButton.setBounds(324,48,144,24);
		shapeChoice.addItem("square");
		shapeChoice.addItem("triangular");
		try {
			shapeChoice.select(0);
		}
		catch (IllegalArgumentException e) { }
		activePanel.add(shapeChoice);
		shapeChoice.setBounds(0,24,96,25);
		labelChoice.addItem("labels");
		labelChoice.addItem("no labels");
		try {
			labelChoice.select(0);
		}
		catch (IllegalArgumentException e) { }
		activePanel.add(labelChoice);
		labelChoice.setBounds(108,24,96,25);
		info.setText("Constraints are propagated automatically.");
		activePanel.add(info);
		info.setBounds(0,60,240,24);
		normaliseButton.setLabel("Normalise");
		activePanel.add(normaliseButton);
		normaliseButton.setBackground(java.awt.Color.lightGray);
		normaliseButton.setBounds(252,48,72,24);
		add(tablePane);
		tablePane.setBounds(0,120,492,264);
		message.setText("Enter number of elements, select kind of relation, and click \'New Table\'.");
		add(message);
		message.setBounds(0,384,492,28);
		//}}
	
		//{{REGISTER_LISTENERS
		SymAction lSymAction = new SymAction();
		newTableButton.addActionListener(lSymAction);
		fillAllCellsButton.addActionListener(lSymAction);
		fillOneCellButton.addActionListener(lSymAction);
		SymItem lSymItem = new SymItem();
		shapeChoice.addItemListener(lSymItem);
		labelChoice.addItemListener(lSymItem);
		normaliseButton.addActionListener(lSymAction);
		//}}
		
		controller = new CPTableController(message);
	}
	
	//{{DECLARE_CONTROLS
	java.awt.Label header = new java.awt.Label();
	java.awt.Panel activePanel = new java.awt.Panel();
	java.awt.Button newTableButton = new java.awt.Button();
	java.awt.Choice relationChoice = new java.awt.Choice();
	java.awt.Label numberOfElementsLabel = new java.awt.Label();
	java.awt.TextField numberOfElements = new java.awt.TextField();
	java.awt.Label kindOfRelationLabel = new java.awt.Label();
	java.awt.Button fillAllCellsButton = new java.awt.Button();
	java.awt.Button fillOneCellButton = new java.awt.Button();
	java.awt.Choice shapeChoice = new java.awt.Choice();
	java.awt.Choice labelChoice = new java.awt.Choice();
	java.awt.Label info = new java.awt.Label();
	java.awt.Button normaliseButton = new java.awt.Button();
	java.awt.ScrollPane tablePane = new java.awt.ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
	java.awt.Label message = new java.awt.Label();
	//}}

	private void displayTable()
	{
		view.update();
		tablePane.doLayout();
		tablePane.repaint();
	}

	class SymAction implements java.awt.event.ActionListener
	{
		public void actionPerformed(java.awt.event.ActionEvent event)
		{
			Object object = event.getSource();
			if (object == newTableButton)
				newTableButton_ActionPerformed(event);
			else if (object == fillAllCellsButton)
				fillAllCellsButton_ActionPerformed(event);
			else if (object == fillOneCellButton)
				fillOneCellButton_ActionPerformed(event);
			else if (object == normaliseButton)
				normaliseButton_ActionPerformed(event);
			
		}
	}

	void newTableButton_ActionPerformed(java.awt.event.ActionEvent event)
	{
		int n;
		
		try
		{
			n = Integer.parseInt(numberOfElements.getText());
		}
		catch (NumberFormatException e)
		{
			message.setText(numberOfElements.getText() + 
				" is not a valid number of elements");
			return;
		}
		if (n > 0)
		{
			switch (relationChoice.getSelectedIndex())
			{
			case 0:
				table = new PointTableRepresentation(n);
				view = new TableView(table, 2, 
					labelChoice.getSelectedIndex() == 0,
					shapeChoice.getSelectedIndex() == 0, controller);
				break;
			case 1:
				table = new AllenPeriodTableRepresentation(n);
				view = new TableView(table, 32,
					labelChoice.getSelectedIndex() == 0,
					shapeChoice.getSelectedIndex() == 0, controller);
				break;
			case 2:
				table = new SymbolicPeriodTableRepresentation(n);
				view = new TableView(table, 7,
					labelChoice.getSelectedIndex() == 0,
					shapeChoice.getSelectedIndex() == 0, controller);
				break;
			case 3:
				table = new PointPeriodTableRepresentation(n);
				view = new TableView(table, 16,
					labelChoice.getSelectedIndex() == 0,
					shapeChoice.getSelectedIndex() == 0, controller);
				break;
			case 4:
				table = new EventTableRepresentation(n);
				view = new TableView(table, 1,
					labelChoice.getSelectedIndex() == 0,
					shapeChoice.getSelectedIndex() == 0, controller);
			}
			controller.setTable(table);
			controller.setView(view);
			tablePane.add(view);
			displayTable();
		}
		else
		{
			message.setText(numberOfElements.getText() + 
				" is not a valid number of elements");
			return;
		}
		message.setText("Enter relations in the cells or use the buttons to set them randomly");
	}
	
	void fillAllCellsButton_ActionPerformed(java.awt.event.ActionEvent event)
	{
		Relation r;

		if (table != null && table.isConsistent())
		{
			outerLoop:
			for (int j = 1; j < table.getSize(); j++)
				for (int i = 0; i < j; i++)
				{
					if (!table.cell[i][j].isDeterminate())
					{
						message.setText(message.getText() + " Filling...");
						try
						{
							r = (Relation)table.cell[i][j].clone();
						}
						catch (CloneNotSupportedException e)
						{
			    			throw new RuntimeException(
			    				"Unexpected CloneNotSupportedException: "
			    				+ table.cell[i][j]);
						}
						do
							r.setRandom();
						while (!table.cell[i][j].includes(r));
						controller.cellChanged(i, j, r);
						if (!table.isConsistent()) break outerLoop;
					}
				}
			message.setText(message.getText() + " Done.");
		}
	}

	void fillOneCellButton_ActionPerformed(java.awt.event.ActionEvent event)
	{
		int i, j;
		Relation r;

		if (table != null && table.isConsistent())
		{
			checkNotDeterminate: 
			{
				for (i = 0; i < table.getSize(); i++)
					for (j = 0; j < table.getSize(); j++)
						if (i != j && !table.cell[i][j].isDeterminate()) 
							break checkNotDeterminate;
				return;
			}
			do
			{
				i = (int)(Math.random() * table.getSize());
				j = (int)(Math.random() * table.getSize());
			}
			while (i == j || table.cell[i][j].isDeterminate());
			try
			{
				r = (Relation)table.cell[i][j].clone();
			}
			catch (CloneNotSupportedException e)
			{
				throw new RuntimeException(
			    	"Unexpected CloneNotSupportedException: "
			    	+ table.cell[i][j]);
			}
			do
				r.setRandom();
			while (!table.cell[i][j].includes(r));
			controller.cellChanged(i, j, r);
		}
	}

	class SymItem implements java.awt.event.ItemListener
	{
		public void itemStateChanged(java.awt.event.ItemEvent event)
		{
			Object object = event.getSource();
			if (object == shapeChoice)
				shapeChoice_ItemStateChanged(event);
			else if (object == labelChoice)
				labelChoice_ItemStateChanged(event);
		}
	}

	void shapeChoice_ItemStateChanged(java.awt.event.ItemEvent event)
	{
		if (view != null)
		{
			view.setSquare(shapeChoice.getSelectedIndex() == 0);
			displayTable();
		}
	}

	void labelChoice_ItemStateChanged(java.awt.event.ItemEvent event)
	{
		if (view != null)
		{
			view.setLabelsVisible(labelChoice.getSelectedIndex() == 0);
			displayTable();
		}
	}

	void normaliseButton_ActionPerformed(java.awt.event.ActionEvent event)
	{
		if (table != null)
		{
			message.setText("Normalising...");
			table.normalise();
			displayTable();
			message.setText("Normalised");
		}
	}
}
