package main;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import signals.Clock;
import signals.Signals;


public class DialogBox extends JDialog {

	private static final long serialVersionUID = 1L;
	
	private JLabel clockLabel;
	private JTextField nameField, ratioField, waveField;
	private JComboBox clockBox,clockForRatioBox;
	private JCheckBox displayRisingEdgesBox,beginOnRisingEdgeBox,setUpBox,clkToQdelayBox,clockDependencyBox;
	
	private JPanel content;
	private JPanel nameContent;
	private JPanel clockContent;
	private JPanel ratioContent;
	private JPanel sliderContent;
	
	private JPanel waveContent;
	
	public boolean valid=false;
	public boolean displayRisingEdges,beginOnRisingEdge;
	public String name;
	public int clockDomain=-1;
	public float ratio;
	public boolean clkDependency;
	public int freq=-1;
	public boolean setUp=false;
	public boolean clkToQdelay=false;
	
	public int[] waveSet;
	
	private boolean onlyName=false;
	private boolean clock=false,dependsOnClk=false;
	private int[] clockDomainId = new int[50];
	private int[] clockDomainForRatioId = new int[50];
	
	// Signal Properties
	public DialogBox(JFrame parent, String title, Signals s){
		super(parent, title, true);
		this.setSize(230, 300);
		this.setLocationRelativeTo(null);
		this.setResizable(false);
		this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		this.initComponent(s);
	}
	
	// Bus field names
	public DialogBox(JFrame parent, String title){
		super(parent, title, true);
		onlyName=true;
		this.setSize(250, 200);
		this.setLocationRelativeTo(null);
		this.setResizable(false);
		this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		this.initComponent(new Clock("",20));
	}
	
	// Signal Values
	public DialogBox(JFrame parent, String title, Signals s, boolean values){
		super(parent, title, true);
		this.setSize(400, 150);
		this.setLocationRelativeTo(null);
		this.setResizable(false);
		this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		waveSet  = new int[500];
		displayValueField(s);
	}
	
	// Text
	public DialogBox(JFrame parent, String title, String val)
	{
		super(parent, title, true);
		onlyName=true;
		this.setSize(250, 200);
		this.setLocationRelativeTo(null);
		this.setResizable(false);
		this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
		
		content = new JPanel();
		nameContent = new JPanel();
		
		// Name
				nameField = new JTextField("");
				nameField.setPreferredSize(new Dimension(100, 25));
				nameContent.setBorder(BorderFactory.createTitledBorder("Set name"));
				nameContent.add(nameField);
		// Valid // Cancel
				JPanel control = new JPanel();
				JButton okButton = new JButton("Valid");
				this.getRootPane().setDefaultButton(okButton);
				okButton.addActionListener(new ActionListener(){
					public void actionPerformed(ActionEvent arg0) 
					{
						name=nameField.getText();

						
						valid=true;
						setVisible(false);
					}			
				});
				JButton cancelBouton = new JButton("Cancel");
				cancelBouton.addActionListener(new ActionListener()
				{
					public void actionPerformed(ActionEvent arg0) 
					{
						valid=false;
						setVisible(false);
					}			
				});
				
				/********** Add Elements to dialog Box **********/
				content.add(nameContent);
				control.add(okButton);
				control.add(cancelBouton);
				this.getContentPane().add(content, BorderLayout.CENTER);
				this.getContentPane().add(control, BorderLayout.SOUTH);
		
		}
	
	public void showDialog(){
		this.setVisible(true);		
	}
	
	private void initComponent(Signals s){
		
		content = new JPanel();
		nameContent = new JPanel();
		clockContent = new JPanel();
		ratioContent = new JPanel();
		sliderContent = new JPanel();
		
		clock=s.clock;
		dependsOnClk=s.dependsOnClk;
		
		/********** Create Elements **********/
		
		// Name
		nameField = new JTextField(s.name);
		nameField.setPreferredSize(new Dimension(100, 25));
		nameContent.setBorder(BorderFactory.createTitledBorder("Set name"));
		nameContent.add(nameField);
		
		// Display Rising Edges
		displayRisingEdgesBox = new JCheckBox("Display Rising Edges");
		displayRisingEdgesBox.setSelected(s.displayRisingEdges);
		displayRisingEdges=s.displayRisingEdges;
		displayRisingEdgesBox.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent event){
				displayRisingEdges=displayRisingEdgesBox.isSelected();
			}
		});
		
		// Begin on Rising Edge
		beginOnRisingEdgeBox = new JCheckBox("Begin on Rising Edge");
		beginOnRisingEdgeBox.setSelected(s.wave[0]==1);
		beginOnRisingEdge=(s.wave[0]==1);
		beginOnRisingEdgeBox.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent event){
				beginOnRisingEdge=beginOnRisingEdgeBox.isSelected();
			}
		});
		
		
		// Clock Speed
		JSlider slide = new JSlider();
		slide.setMaximum(105);
		slide.setMinimum(5);
		slide.setValue(s.widthUnit);
		freq=s.widthUnit;
		slide.setPaintTicks(true);
		slide.setPaintLabels(true);
		slide.setMinorTickSpacing(10);
		slide.setMajorTickSpacing(20);
		slide.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent event){
				freq=((JSlider)event.getSource()).getValue();
				sliderContent.setBorder(BorderFactory.createTitledBorder("Period: "+freq));
			}
		});
		sliderContent.setBorder(BorderFactory.createTitledBorder("Period: "+s.widthUnit));
		sliderContent.add(slide);

		// Clock Dependency
		clockDependencyBox = new JCheckBox("Create clock dependency");
		clockDependencyBox.setSelected(s.dependsOnClk);
		clockDependencyBox.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent event){
				sliderContent.setVisible(!clockDependencyBox.isSelected());
				ratioContent.setVisible(clockDependencyBox.isSelected());
			}
		});
		
		// Clock Domain
		int selectedIndex=0;
		int selectedIndexForRatio=0;
		int temp=0;
		int tempForRatio=0;
		boolean clkDomainEmpty=true;
		boolean clkDomainForRatioEmpty=true;
		clockBox = new JComboBox();
		clockForRatioBox = new JComboBox();
		for (int i=0; i<ChronoWindow.chrono.get(ChronoWindow.active).signals.size(); i++){
			if (ChronoWindow.chrono.get(ChronoWindow.active).signals.get(i).clock){
				// ClockDomain
				clockBox.addItem(ChronoWindow.chrono.get(ChronoWindow.active).signals.get(i).name);
				clockDomainId[temp]=ChronoWindow.chrono.get(ChronoWindow.active).signals.get(i).id;
				if (ChronoWindow.chrono.get(ChronoWindow.active).signals.get(i).id == s.clockDomainId) selectedIndex=temp;
				temp++;
				clkDomainEmpty=false;
				
				// ClockDomainForRatio
				if (ChronoWindow.chrono.get(ChronoWindow.active).signals.get(i).id!= s.id && !ChronoWindow.chrono.get(ChronoWindow.active).signals.get(i).dependsOnClk){
					clockForRatioBox.addItem(ChronoWindow.chrono.get(ChronoWindow.active).signals.get(i).name);
					clockDomainForRatioId[tempForRatio]=ChronoWindow.chrono.get(ChronoWindow.active).signals.get(i).id;
					clkDomainForRatioEmpty=false;
					if (ChronoWindow.chrono.get(ChronoWindow.active).signals.get(i).id == s.clockDomainId) selectedIndexForRatio=tempForRatio;
					tempForRatio++;
				}
				
				
			}
		}
		if (clkDomainEmpty){
			clockBox.addItem(null);
		}
		else{
			clockBox.setSelectedIndex(selectedIndex);
		}
		if (clkDomainForRatioEmpty){
			clockForRatioBox.addItem(null);
		}
		else{
			clockForRatioBox.setSelectedIndex(selectedIndexForRatio);
		}
		clockLabel = new JLabel("Select clock :");
		clockContent.setBorder(BorderFactory.createTitledBorder("Clock Domain"));
		clockContent.add(clockLabel);
		clockContent.add(clockBox);
		
		// Clock Ratio
		ratioField = new JTextField(Float.toString(s.ratio));
		ratioField.setPreferredSize(new Dimension(100, 25));
		ratioContent.setBorder(BorderFactory.createTitledBorder("Clock Domain Ratio"));
		ratioContent.add(clockForRatioBox);
		ratioContent.add(ratioField);
		
		/** Signal/Bus options (clkToQ and delay) **/	
		// Edge Delay
			setUpBox = new JCheckBox("Add setup time");
			if (s.setUpTime>0){
				setUpBox.setSelected(true);
				setUp=true;
			}
			setUpBox.addChangeListener(new ChangeListener(){
				public void stateChanged(ChangeEvent event){
					setUp=setUpBox.isSelected();
				}
			});
		// Delay
		clkToQdelayBox = new JCheckBox("Left shift");
		clkToQdelayBox.setSelected(s.clkToQdelay);
		clkToQdelay=s.clkToQdelay;
		clkToQdelayBox.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent event){
				clkToQdelay=clkToQdelayBox.isSelected();
			}
		});
		
		// Valid // Cancel
		JPanel control = new JPanel();
		JButton okButton = new JButton("Valid");
		this.getRootPane().setDefaultButton(okButton);
		okButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				name=nameField.getText();

				if (clock){
					if (clockDependencyBox.isSelected()){
						clockDomain=clockDomainForRatioId[clockForRatioBox.getSelectedIndex()];
						ratio = Float.parseFloat(ratioField.getText());
						clkDependency=true;
					}
					else{
						clkDependency=false;
					}
				}
				else if (dependsOnClk){
					clockDomain=clockDomainId[clockBox.getSelectedIndex()];
				}
				valid=true;
				setVisible(false);
			}			
		});
		JButton cancelBouton = new JButton("Cancel");
		cancelBouton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				valid=false;
				setVisible(false);
			}			
		});
		
		/********** Add Elements to dialog Box **********/
		content.add(nameContent);
		content.add(displayRisingEdgesBox);
		content.add(beginOnRisingEdgeBox);
		content.add(clockContent);
		content.add(clockDependencyBox);
		content.add(sliderContent);
		content.add(ratioContent);
		content.add(setUpBox);
		content.add(clkToQdelayBox);
		control.add(okButton);
		control.add(cancelBouton);
		this.getContentPane().add(content, BorderLayout.CENTER);
		this.getContentPane().add(control, BorderLayout.SOUTH);
		
		/********** Set Elements Visible/Enabled **********/
		nameContent.setVisible(true);
		displayRisingEdgesBox.setVisible(s.clock && !onlyName && s.id!=-1);
		beginOnRisingEdgeBox.setVisible(s.clock && !onlyName && s.id!=-1);
		clockContent.setVisible(!s.clock && s.dependsOnClk && !onlyName);
		clockDependencyBox.setVisible(s.clock && !onlyName && s.id!=-1);
		clockDependencyBox.setEnabled(!clkDomainForRatioEmpty && s.id!=-1);
		sliderContent.setVisible(!s.dependsOnClk && !onlyName); // Toggles via dependency for clock
		ratioContent.setVisible(s.clock && s.dependsOnClk && !clkDomainEmpty && !onlyName); // Toggles via dependency for clock
		setUpBox.setVisible(!s.clock && s.id!=-1 && !onlyName && !s.bus);
		clkToQdelayBox.setVisible(!s.clock && s.id!=-1 && !onlyName);
	}
	
	public void displayValueField( Signals s){
		
		content = new JPanel();
		waveContent = new JPanel();
		
		// Wave values
		String wave = "";
		int tmp = s.wave[0], index=0;
		for (int i=0; i<s.wave.length; i++){
			if (s.wave[i]!=tmp){
				tmp=s.wave[i];
				index=i;
			}
		}
		for (int i=0; i<index; i++)	wave+=s.wave[i];
		waveField = new JTextField(wave);
		waveField.setPreferredSize(new Dimension(300, 25));
		waveContent.setBorder(BorderFactory.createTitledBorder("Wave values"));
		waveContent.add(waveField);
		
		// Valid // Cancel
		JPanel control = new JPanel();
		JButton okButton = new JButton("Valid");
		this.getRootPane().setDefaultButton(okButton);
		okButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				String tmp = waveField.getText();
            	tmp=tmp.replaceAll(" ", "");
            	int toFill=0;
            	for (int i=0; i<waveSet.length; i++){
            		if (i<tmp.length()){
            			char c = tmp.charAt(i);
            			String  sTmp = String.valueOf(c);
            			waveSet[i]=Integer.parseInt(sTmp);
            			toFill=waveSet[i];
            		}
            		else{
            			if (toFill==0) waveSet[i]=1;
            			if (toFill==1) waveSet[i]=0;
            		}
            	}
            	valid=true;
				setVisible(false);
			}			
		});
		JButton cancelBouton = new JButton("Cancel");
		cancelBouton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				valid=false;
				setVisible(false);
			}			
		});
		
		content.add(waveContent);
		control.add(okButton);
		control.add(cancelBouton);
		this.getContentPane().add(content, BorderLayout.CENTER);
		this.getContentPane().add(control, BorderLayout.SOUTH);
	}
}