package chrono;

import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
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.JRootPane;
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;
  private JTextField ratioField;
  private JTextField waveField;
  private JComboBox clockBox;
  private JComboBox clockForRatioBox;
  private JCheckBox displayRisingEdgesBox;
  private JCheckBox beginOnRisingEdgeBox;
  private JCheckBox setUpBox;
  private JCheckBox clkToQdelayBox;
  private JCheckBox 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;
  public boolean 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;
  private boolean dependsOnClk = false;
  private int[] clockDomainId = new int[50];
  private int[] clockDomainForRatioId = new int[50];
  
  public DialogBox(JFrame parent, String title, Signals s)
  {
    super(parent, title, true);
    setSize(230, 300);
    setLocationRelativeTo(null);
    setResizable(false);
    setDefaultCloseOperation(2);
    initComponent(s);
  }
  
  public DialogBox(JFrame parent, String title)
  {
    super(parent, title, true);
    this.onlyName = true;
    setSize(250, 200);
    setLocationRelativeTo(null);
    setResizable(false);
    setDefaultCloseOperation(2);
    initComponent(new Clock("", 20));
  }
  
  public DialogBox(JFrame parent, String title, Signals s, boolean values)
  {
    super(parent, title, true);
    setSize(400, 150);
    setLocationRelativeTo(null);
    setResizable(false);
    setDefaultCloseOperation(2);
    this.waveSet = new int['?'];
    displayValueField(s);
  }
  
  public void showDialog()
  {
    setVisible(true);
  }
  
  private void initComponent(Signals s)
  {
    this.content = new JPanel();
    this.nameContent = new JPanel();
    this.clockContent = new JPanel();
    this.ratioContent = new JPanel();
    this.sliderContent = new JPanel();
    
    this.clock = s.clock;
    this.dependsOnClk = s.dependsOnClk;
    
    this.nameField = new JTextField(s.name);
    this.nameField.setPreferredSize(new Dimension(100, 25));
    this.nameContent.setBorder(BorderFactory.createTitledBorder("Set name"));
    this.nameContent.add(this.nameField);
    
    this.displayRisingEdgesBox = new JCheckBox("Display Rising Edges");
    this.displayRisingEdgesBox.setSelected(s.displayRisingEdges);
    this.displayRisingEdges = s.displayRisingEdges;
    this.displayRisingEdgesBox.addChangeListener(new ChangeListener()
    {
      public void stateChanged(ChangeEvent event)
      {
        DialogBox.this.displayRisingEdges = DialogBox.this.displayRisingEdgesBox.isSelected();
      }
    });
    this.beginOnRisingEdgeBox = new JCheckBox("Begin on Rising Edge");
    this.beginOnRisingEdgeBox.setSelected(s.wave[0] == 1);
    this.beginOnRisingEdge = (s.wave[0] == 1);
    this.beginOnRisingEdgeBox.addChangeListener(new ChangeListener()
    {
      public void stateChanged(ChangeEvent event)
      {
        DialogBox.this.beginOnRisingEdge = DialogBox.this.beginOnRisingEdgeBox.isSelected();
      }
    });
    JSlider slide = new JSlider();
    slide.setMaximum(105);
    slide.setMinimum(5);
    slide.setValue(s.widthUnit);
    this.freq = s.widthUnit;
    slide.setPaintTicks(true);
    slide.setPaintLabels(true);
    slide.setMinorTickSpacing(10);
    slide.setMajorTickSpacing(20);
    slide.addChangeListener(new ChangeListener()
    {
      public void stateChanged(ChangeEvent event)
      {
        DialogBox.this.freq = ((JSlider)event.getSource()).getValue();
        DialogBox.this.sliderContent.setBorder(BorderFactory.createTitledBorder("Period: " + DialogBox.this.freq));
      }
    });
    this.sliderContent.setBorder(BorderFactory.createTitledBorder("Period: " + s.widthUnit));
    this.sliderContent.add(slide);
    
    this.clockDependencyBox = new JCheckBox("Create clock dependency");
    this.clockDependencyBox.setSelected(s.dependsOnClk);
    this.clockDependencyBox.addChangeListener(new ChangeListener()
    {
      public void stateChanged(ChangeEvent event)
      {
        DialogBox.this.sliderContent.setVisible(!DialogBox.this.clockDependencyBox.isSelected());
        DialogBox.this.ratioContent.setVisible(DialogBox.this.clockDependencyBox.isSelected());
      }
    });
    int selectedIndex = 0;
    int selectedIndexForRatio = 0;
    int temp = 0;
    int tempForRatio = 0;
    boolean clkDomainEmpty = true;
    boolean clkDomainForRatioEmpty = true;
    this.clockBox = new JComboBox();
    this.clockForRatioBox = new JComboBox();
    for (int i = 0; i < ((ChronoPanel)ChronoFrame.chrono.get(ChronoFrame.active)).signals.size(); i++) {
      if (((Signals)((ChronoPanel)ChronoFrame.chrono.get(ChronoFrame.active)).signals.get(i)).clock)
      {
        this.clockBox.addItem(((Signals)((ChronoPanel)ChronoFrame.chrono.get(ChronoFrame.active)).signals.get(i)).name);
        this.clockDomainId[temp] = ((Signals)((ChronoPanel)ChronoFrame.chrono.get(ChronoFrame.active)).signals.get(i)).id;
        if (((Signals)((ChronoPanel)ChronoFrame.chrono.get(ChronoFrame.active)).signals.get(i)).id == s.clockDomainId) {
          selectedIndex = temp;
        }
        temp++;
        clkDomainEmpty = false;
        if ((((Signals)((ChronoPanel)ChronoFrame.chrono.get(ChronoFrame.active)).signals.get(i)).id != s.id) && (!((Signals)((ChronoPanel)ChronoFrame.chrono.get(ChronoFrame.active)).signals.get(i)).dependsOnClk))
        {
          this.clockForRatioBox.addItem(((Signals)((ChronoPanel)ChronoFrame.chrono.get(ChronoFrame.active)).signals.get(i)).name);
          this.clockDomainForRatioId[tempForRatio] = ((Signals)((ChronoPanel)ChronoFrame.chrono.get(ChronoFrame.active)).signals.get(i)).id;
          clkDomainForRatioEmpty = false;
          if (((Signals)((ChronoPanel)ChronoFrame.chrono.get(ChronoFrame.active)).signals.get(i)).id == s.clockDomainId) {
            selectedIndexForRatio = tempForRatio;
          }
          tempForRatio++;
        }
      }
    }
    if (clkDomainEmpty) {
      this.clockBox.addItem(null);
    } else {
      this.clockBox.setSelectedIndex(selectedIndex);
    }
    if (clkDomainForRatioEmpty) {
      this.clockForRatioBox.addItem(null);
    } else {
      this.clockForRatioBox.setSelectedIndex(selectedIndexForRatio);
    }
    this.clockLabel = new JLabel("Select clock :");
    this.clockContent.setBorder(BorderFactory.createTitledBorder("Clock Domain"));
    this.clockContent.add(this.clockLabel);
    this.clockContent.add(this.clockBox);
    
    this.ratioField = new JTextField(Float.toString(s.ratio));
    this.ratioField.setPreferredSize(new Dimension(100, 25));
    this.ratioContent.setBorder(BorderFactory.createTitledBorder("Clock Domain Ratio"));
    this.ratioContent.add(this.clockForRatioBox);
    this.ratioContent.add(this.ratioField);
    
    this.setUpBox = new JCheckBox("Add setup time");
    if (s.setUpTime > 0)
    {
      this.setUpBox.setSelected(true);
      this.setUp = true;
    }
    this.setUpBox.addChangeListener(new ChangeListener()
    {
      public void stateChanged(ChangeEvent event)
      {
        DialogBox.this.setUp = DialogBox.this.setUpBox.isSelected();
      }
    });
    this.clkToQdelayBox = new JCheckBox("Left shift");
    this.clkToQdelayBox.setSelected(s.clkToQdelay);
    this.clkToQdelay = s.clkToQdelay;
    this.clkToQdelayBox.addChangeListener(new ChangeListener()
    {
      public void stateChanged(ChangeEvent event)
      {
        DialogBox.this.clkToQdelay = DialogBox.this.clkToQdelayBox.isSelected();
      }
    });
    JPanel control = new JPanel();
    JButton okButton = new JButton("Valid");
    getRootPane().setDefaultButton(okButton);
    okButton.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent arg0)
      {
        DialogBox.this.name = DialogBox.this.nameField.getText();
        if (DialogBox.this.clock)
        {
          if (DialogBox.this.clockDependencyBox.isSelected())
          {
            DialogBox.this.clockDomain = DialogBox.this.clockDomainForRatioId[DialogBox.this.clockForRatioBox.getSelectedIndex()];
            DialogBox.this.ratio = Float.parseFloat(DialogBox.this.ratioField.getText());
            DialogBox.this.clkDependency = true;
          }
          else
          {
            DialogBox.this.clkDependency = false;
          }
        }
        else if (DialogBox.this.dependsOnClk) {
          DialogBox.this.clockDomain = DialogBox.this.clockDomainId[DialogBox.this.clockBox.getSelectedIndex()];
        }
        DialogBox.this.valid = true;
        DialogBox.this.setVisible(false);
      }
    });
    JButton cancelBouton = new JButton("Cancel");
    cancelBouton.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent arg0)
      {
        DialogBox.this.valid = false;
        DialogBox.this.setVisible(false);
      }
    });
    this.content.add(this.nameContent);
    this.content.add(this.displayRisingEdgesBox);
    this.content.add(this.beginOnRisingEdgeBox);
    this.content.add(this.clockContent);
    this.content.add(this.clockDependencyBox);
    this.content.add(this.sliderContent);
    this.content.add(this.ratioContent);
    this.content.add(this.setUpBox);
    this.content.add(this.clkToQdelayBox);
    control.add(okButton);
    control.add(cancelBouton);
    getContentPane().add(this.content, "Center");
    getContentPane().add(control, "South");
    
    this.nameContent.setVisible(true);
    this.displayRisingEdgesBox.setVisible((s.clock) && (!this.onlyName) && (s.id != -1));
    this.beginOnRisingEdgeBox.setVisible((s.clock) && (!this.onlyName) && (s.id != -1));
    this.clockContent.setVisible((!s.clock) && (s.dependsOnClk) && (!this.onlyName));
    this.clockDependencyBox.setVisible((s.clock) && (!this.onlyName) && (s.id != -1));
    this.clockDependencyBox.setEnabled((!clkDomainForRatioEmpty) && (s.id != -1));
    this.sliderContent.setVisible((!s.dependsOnClk) && (!this.onlyName));
    this.ratioContent.setVisible((s.clock) && (s.dependsOnClk) && (!clkDomainEmpty) && (!this.onlyName));
    this.setUpBox.setVisible((!s.clock) && (s.id != -1) && (!this.onlyName) && (!s.bus));
    this.clkToQdelayBox.setVisible((!s.clock) && (s.id != -1) && (!this.onlyName));
  }
  
  public void displayValueField(Signals s)
  {
    this.content = new JPanel();
    this.waveContent = new JPanel();
    
    String wave = "";
    int tmp = s.wave[0];int 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 = wave + s.wave[i];
    }
    this.waveField = new JTextField(wave);
    this.waveField.setPreferredSize(new Dimension(300, 25));
    this.waveContent.setBorder(BorderFactory.createTitledBorder("Wave values"));
    this.waveContent.add(this.waveField);
    
    JPanel control = new JPanel();
    JButton okButton = new JButton("Valid");
    getRootPane().setDefaultButton(okButton);
    okButton.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent arg0)
      {
        String tmp = DialogBox.this.waveField.getText();
        tmp = tmp.replaceAll(" ", "");
        int toFill = 0;
        for (int i = 0; i < DialogBox.this.waveSet.length; i++) {
          if (i < tmp.length())
          {
            char c = tmp.charAt(i);
            String sTmp = String.valueOf(c);
            DialogBox.this.waveSet[i] = Integer.parseInt(sTmp);
            toFill = DialogBox.this.waveSet[i];
          }
          else
          {
            if (toFill == 0) {
              DialogBox.this.waveSet[i] = 1;
            }
            if (toFill == 1) {
              DialogBox.this.waveSet[i] = 0;
            }
          }
        }
        DialogBox.this.valid = true;
        DialogBox.this.setVisible(false);
      }
    });
    JButton cancelBouton = new JButton("Cancel");
    cancelBouton.addActionListener(new ActionListener()
    {
      public void actionPerformed(ActionEvent arg0)
      {
        DialogBox.this.valid = false;
        DialogBox.this.setVisible(false);
      }
    });
    this.content.add(this.waveContent);
    control.add(okButton);
    control.add(cancelBouton);
    getContentPane().add(this.content, "Center");
    getContentPane().add(control, "South");
  }
}
