package sim.lib.memory;

import java.awt.*;
import java.awt.event.*;

import sim.util.SimSeparator;

public class RegisterProperties extends Container implements ActionListener, FocusListener {

	private TextField editBus = new TextField(5);
	private TextField editName = new TextField(10);
	private TextField editDelay = new TextField(5);
	private TextField editContent = new TextField(5);
	private double oldDelay;
	private int oldBus;
	private String oldName;
	private String oldContent;
	private int wordLenght;
	private Label configure = new Label("Configuration");
	private Label simulation = new Label("Simulation");

	public RegisterProperties(int bus, double delay, String content, String name) {
		super();
		this.setLayout(new BorderLayout(0, 15));

		this.oldBus = bus;
		this.editBus.addActionListener(this);
		this.editBus.addFocusListener(this);
		this.editBus.setText(Integer.toString(bus));

		this.oldDelay = delay;
		this.editDelay.addActionListener(this);
		this.editDelay.addFocusListener(this);
		this.editDelay.setText(Double.toString(delay));

		this.oldName = name;
		this.editName.addActionListener(this);
		this.editName.addFocusListener(this);
		this.editName.setText(name);

		this.oldContent = content;
		this.editContent.addActionListener(this);
		this.editContent.addFocusListener(this);
		this.editContent.setText(content);

		this.wordLenght = Integer.toString((int) Math.pow(2, bus) - 1, 16).length();

		// configuration
		Panel big = new Panel(new BorderLayout(0, 15));

		Panel p = new Panel(new BorderLayout());
		p.add(this.configure, BorderLayout.WEST);
		p.add(new SimSeparator(), BorderLayout.CENTER);
		big.add(p, BorderLayout.NORTH);

		Panel p2 = new Panel(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();

		c.fill = GridBagConstraints.NONE;
		c.gridheight = 1;
		c.gridwidth = 1;
		c.weightx = 1;
		c.weighty = 0;
		c.gridy = 0;

		c.gridx = 0;
		c.anchor = GridBagConstraints.WEST;

		p = new Panel(new FlowLayout(FlowLayout.LEFT, 0, 0));
		p.add(new Label("Bus Size"));
		p.add(this.editBus);
		p2.add(p, c);

		c.gridx = 1;
		c.anchor = GridBagConstraints.EAST;

		p = new Panel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
		p.add(new Label("Name"));
		p.add(this.editName);
		p2.add(p, c);

		big.add(p2, BorderLayout.CENTER);
		this.add(big, BorderLayout.NORTH);

		// simulation
		big = new Panel(new BorderLayout(0, 15));

		p = new Panel(new BorderLayout());
		p.add(this.simulation, BorderLayout.WEST);
		p.add(new SimSeparator(), BorderLayout.CENTER);
		big.add(p, BorderLayout.NORTH);

		p2 = new Panel(new GridBagLayout());

		c.gridx = 0;
		c.anchor = GridBagConstraints.WEST;

		p = new Panel(new FlowLayout(FlowLayout.LEFT, 0, 0));
		p.add(new Label("Propagation Delay"));
		p.add(this.editDelay);
		p2.add(p, c);

		c.gridx = 1;
		c.anchor = GridBagConstraints.EAST;

		p = new Panel(new FlowLayout(FlowLayout.RIGHT, 0, 0));
		p.add(new Label("Content"));
		p.add(this.editContent);
		p2.add(p, c);

		big.add(p2, BorderLayout.CENTER);
		this.add(big, BorderLayout.CENTER);
	}

	public void addNotify() {
		super.addNotify();
		this.setSize(320, this.editBus.getPreferredSize().height * 2 + this.simulation.getPreferredSize().height * 2 + 45);
	}

	public void actionPerformed(ActionEvent e) {
		TextField source = (TextField) e.getSource();

		if (source == this.editDelay) {
			this.getDelay();
		} else if (source == this.editBus) {
			this.getBusSize();
		} else if (source == this.editName) {
			this.getRegisterName();
		} else if (source == this.editContent) {
			this.getContent();
		}
	}

	public void focusGained(FocusEvent e) {
	}

	public void focusLost(FocusEvent e) {
		TextField source = (TextField) e.getSource();

		if (source == this.editDelay) {
			this.getDelay();
		} else if (source == this.editBus) {
			this.getBusSize();
		} else if (source == this.editName) {
			this.getRegisterName();
		} else if (source == this.editContent) {
			this.getContent();
		}
	}

	public int getBusSize() {
		int newBus;

		try {
			newBus = Integer.valueOf(this.editBus.getText()).intValue();

			if ((newBus > 1) && (newBus != this.oldBus) && (newBus <= 32)) {
				this.oldBus = newBus;
				this.wordLenght = Integer.toString((int) Math.pow(2, newBus) - 1, 16).length();

				this.oldContent = "0";

				for (int loop = 1; loop < this.wordLenght; loop++) {
					this.oldContent = "0" + this.oldContent;
				}

				this.editContent.setText(this.oldContent);
			}
		} catch (NumberFormatException nfe) {
		}

		this.editBus.setText(Integer.toString(this.oldBus));

		return this.oldBus;
	}

	public String getContent() {
		int loop;
		String newContent, smallest = new String();

		try {
			newContent = this.editContent.getText();

			if ((newContent.length() > 0) && (newContent.length() <= this.wordLenght)) {
				for (loop = 0; loop < newContent.length(); loop++) {
					if (newContent.charAt(loop) != '-') {
						smallest = smallest + newContent.charAt(loop);
					} else {
						smallest = smallest + "0";
					}
				}

				if (Integer.valueOf(smallest, 16).intValue() < Math.pow(2, this.oldBus)) {
					for (loop = newContent.length(); loop < this.wordLenght; loop++) {
						newContent = "0" + newContent;
					}

					this.oldContent = newContent;
				}
			}
		} catch (NumberFormatException nfe) {
		}

		this.editContent.setText(this.oldContent);

		return this.oldContent;
	}

	public double getDelay() {
		double newDelay;

		try {
			newDelay = Double.valueOf(this.editDelay.getText()).doubleValue();

			if (newDelay >= 0) {
				this.oldDelay = newDelay;
			}
		} catch (NumberFormatException nfe) {
		}

		this.editDelay.setText(Double.toString(this.oldDelay));

		return this.oldDelay;
	}

	public String getRegisterName() {
		String newName;

		try {
			newName = this.editName.getText();

			if (newName.length() > 0) {
				this.oldName = newName;
			}
		} catch (NumberFormatException nfe) {
		}

		this.editName.setText(this.oldName);

		return this.oldName;
	}

	public Dimension getPreferredSize() {
		return this.getSize();
	}

	public Dimension getMinimumSize() {
		return this.getSize();
	}

	public Dimension getMaximumSize() {
		return this.getSize();
	}
}
