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();
	}
}