/**
 * @author Pavel <b>Herout</b>
 */
 
/*
 * Program lze spustit i jako aplikaci prikazem
 * java Oslava
 */

import java.util.*;
import java.math.*;
import java.text.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

class DatumACas extends Observable {
  private JTextField denTF;
  private JTextField mesicTF;
  private JTextField rokTF;
  private JTextField hodinaTF;
  private JTextField minutaTF;
  private JPanel     zobrazeniPN;
  private Calendar cal;

  DatumACas(String nazev) {
    denTF = new JTextField(2);
    mesicTF = new JTextField(2);
    rokTF = new JTextField(3);
    hodinaTF = new JTextField(2);
    minutaTF = new JTextField(2);

    denTF.setHorizontalAlignment(JTextField.RIGHT);
    mesicTF.setHorizontalAlignment(JTextField.RIGHT);
    rokTF.setHorizontalAlignment(JTextField.RIGHT);
    hodinaTF.setHorizontalAlignment(JTextField.RIGHT);
    minutaTF.setHorizontalAlignment(JTextField.RIGHT);

    denTF.addActionListener(new ALTF());
    mesicTF.addActionListener(new ALTF());
    rokTF.addActionListener(new ALTF());
    hodinaTF.addActionListener(new ALTF());
    minutaTF.addActionListener(new ALTF());
    denTF.addFocusListener(new FATF());
    mesicTF.addFocusListener(new FATF());
    rokTF.addFocusListener(new FATF());
    hodinaTF.addFocusListener(new FATF());
    minutaTF.addFocusListener(new FATF());

    zobrazeniPN = new JPanel();
    TitledBorder zobrTB = BorderFactory.createTitledBorder(" " + nazev + " ");
    zobrazeniPN.setBorder(zobrTB);
    zobrazeniPN.setLayout(new FlowLayout(5));
    zobrazeniPN.add(denTF);
    zobrazeniPN.add(new JLabel("."));
    zobrazeniPN.add(mesicTF);
    zobrazeniPN.add(new JLabel("."));
    zobrazeniPN.add(rokTF);
    zobrazeniPN.add(new JLabel("   "));
    zobrazeniPN.add(hodinaTF);
    zobrazeniPN.add(new JLabel(":"));
    zobrazeniPN.add(minutaTF);
  }

  private class ALTF implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      nactiCas();
    }
  }

  private class FATF extends FocusAdapter {
    public void focusLost(FocusEvent e) {
      nactiCas();
    }
    public void focusGained(FocusEvent e) {
      JTextField tf = (JTextField) e.getSource();
      tf.selectAll();
    }
  }

  public JPanel getPanel() {
    return zobrazeniPN;
  }

  public long getVteriny() {
    return cal.getTimeInMillis() / 1000;
  }

  public Calendar getCalendar() {
    return cal;
  }

  public void vypisCas() {
    SimpleDateFormat sdf = new SimpleDateFormat("d M yyyy HH mm");
    String[] udaje = sdf.format(cal.getTime()).split(" ");
    denTF.setText(udaje[0]);
    mesicTF.setText(udaje[1]);
    rokTF.setText(udaje[2]);
    hodinaTF.setText(udaje[3]);
    minutaTF.setText(udaje[4]);
  }

  public void nastavDatum(Calendar cal) {
    this.cal = cal;
  }

  private int naCislo(JTextField tf) {
    String s = tf.getText();
    return Integer.parseInt(s);
  }

  public void nactiCas() {
    cal = new GregorianCalendar(naCislo(rokTF),
                                naCislo(mesicTF) - 1,
                                naCislo(denTF),
                                naCislo(hodinaTF),
                                naCislo(minutaTF));
    setChanged();
    notifyObservers(new Integer(0));
  }

}

public class Oslava extends JApplet implements Observer {
  private final static DecimalFormat df = new DecimalFormat("#,###.##");
  private DatumACas narozeni;
  private DatumACas oslava;

  private JTextField pocetTF;
  private ButtonGroup casovaJednotkaBG;
  private JRadioButton vterinyRB;
  private JRadioButton minutyRB;
  private JRadioButton hodinyRB;
  private JRadioButton dnyRB;
  private JRadioButton tydnyRB;
  private JRadioButton mesiceRB;
  private JRadioButton rokyRB;
  private int[] naJednotky = {
      Calendar.SECOND, Calendar.MINUTE,
      Calendar.HOUR_OF_DAY,
      Calendar.DAY_OF_MONTH, Calendar.WEEK_OF_YEAR,
      Calendar.MONTH, Calendar.YEAR};
  private int[] naPocet = {
      1, 60, 60 * 60, 60 * 60 * 24,
      60 * 60 * 24 * 7, 60 * 60 * 24 * 365 / 12,
      60 * 60 * 24 * 365};

  public void init() {
    narozeni = new DatumACas("Datum narození");
    oslava = new DatumACas("Datum oslavy");

    narozeni.addObserver(this);
    oslava.addObserver(this);

    pocetTF = new JTextField(10);
    pocetTF.setHorizontalAlignment(JTextField.CENTER);

    casovaJednotkaBG = new ButtonGroup();
    vterinyRB = new JRadioButton("vteřiny");
    minutyRB = new JRadioButton("minuty");
    hodinyRB = new JRadioButton("hodiny");
    dnyRB = new JRadioButton("dny");
    tydnyRB = new JRadioButton("týdny");
    mesiceRB = new JRadioButton("měsíce");
    rokyRB = new JRadioButton("roky", true);

    vterinyRB.setMnemonic(0);
    minutyRB.setMnemonic(1);
    hodinyRB.setMnemonic(2);
    dnyRB.setMnemonic(3);
    tydnyRB.setMnemonic(4);
    mesiceRB.setMnemonic(5);
    rokyRB.setMnemonic(6);

    casovaJednotkaBG.add(vterinyRB);
    casovaJednotkaBG.add(minutyRB);
    casovaJednotkaBG.add(hodinyRB);
    casovaJednotkaBG.add(dnyRB);
    casovaJednotkaBG.add(tydnyRB);
    casovaJednotkaBG.add(mesiceRB);
    casovaJednotkaBG.add(rokyRB);

    this.getContentPane().add(vytvorVnitrek());
    this.obsluhyUdalosti();

    Calendar cal = new GregorianCalendar(1970, 11, 31, 12, 0);
    narozeni.nastavDatum(cal);
    narozeni.vypisCas();
    oslava.nastavDatum(Calendar.getInstance());
    oslava.vypisCas();
    oslava.nactiCas();
  }

  private Container vytvorVnitrek() {
    JPanel vnitrek = new JPanel();
    GridBagLayout gbl = new GridBagLayout();
    vnitrek.setLayout(gbl);
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.insets = new Insets(5, 5, 5, 5);
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.anchor = GridBagConstraints.CENTER;
    gbc.weightx = 0.0;
    gbc.weighty = 0.0;
    gbc.gridwidth = 1;

    JPanel jednPN = new JPanel();
    TitledBorder jednTB = BorderFactory.createTitledBorder(" Časové jednotky ");
    jednPN.setBorder(jednTB);
    jednPN.setLayout(new GridLayout(3, 1));
    JPanel pPN = new JPanel();
    pPN.add(new JLabel("počet"));
    pPN.add(pocetTF);
    jednPN.add(pPN);

    pPN = new JPanel();
    pPN.add(vterinyRB);
    pPN.add(minutyRB);
    pPN.add(hodinyRB);
    jednPN.add(pPN);

    pPN = new JPanel();
    pPN.add(dnyRB);
    pPN.add(tydnyRB);
    pPN.add(mesiceRB);
    pPN.add(rokyRB);
    jednPN.add(pPN);

    gbc.gridx = 0;
    gbc.gridy = 0;
    gbl.setConstraints(narozeni.getPanel(), gbc);
    vnitrek.add(narozeni.getPanel());
    gbc.gridx = 0;
    gbc.gridy = 1;
    gbl.setConstraints(oslava.getPanel(), gbc);
    vnitrek.add(oslava.getPanel());
    gbc.gridx = 0;
    gbc.gridy = 2;
    gbl.setConstraints(jednPN, gbc);
    vnitrek.add(jednPN);

    return vnitrek;
  }

  private void obsluhyUdalosti() {
    vterinyRB.addActionListener(new ALRB());
    minutyRB.addActionListener(new ALRB());
    hodinyRB.addActionListener(new ALRB());
    dnyRB.addActionListener(new ALRB());
    tydnyRB.addActionListener(new ALRB());
    mesiceRB.addActionListener(new ALRB());
    rokyRB.addActionListener(new ALRB());
    pocetTF.addActionListener(new ALpocetTF());
    pocetTF.addFocusListener(new FApocetTF());
  }

  private class ALRB implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      aktualizujPocet();
    }
  }

  private class ALpocetTF implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      aktualizujDatum();
    }
  }

  private class FApocetTF extends FocusAdapter {
    public void focusLost(FocusEvent e) {
      aktualizujDatum();
    }
    public void focusGained(FocusEvent e) {
      zaokrouhli();
      pocetTF.selectAll();
    }
  }

  private String zaokrouhli() {
    return zaokrouhli(pocetTF.getText());
  }

  private String zaokrouhli(String zaokr) {
    StringBuffer b = new StringBuffer(zaokr);
    if (b.indexOf(",") >= 0) {
      b.setCharAt(b.indexOf(","), '.');
    }
    for (int i = 0;  i < b.length();  i++) {
      if (Character.isDigit(b.charAt(i)) == false
          &&  b.charAt(i) != '.') {
        b.deleteCharAt(i);
      }
    }
    String s = b.toString();
    if (s.indexOf(".") >= 0) {
      BigDecimal bd = new BigDecimal(s);
      bd = bd.setScale(0, BigDecimal.ROUND_HALF_UP);
      s = bd.toString();
    }
    pocetTF.setText(df.format(Double.parseDouble(s)));
    return s;
  }

  private void presnyPocet(int cisloJednotky) {
    Calendar narCal = narozeni.getCalendar();
    Calendar oslCal = oslava.getCalendar();
    boolean stejne = true;
    for (int i = 1;  i < cisloJednotky;  i++) {
      if (i == 4) {
        continue;   // nekontrolovat tydny
      }
      if (narCal.get(naJednotky[i]) != oslCal.get(naJednotky[i])) {
        stejne = false;
      }
    }
    double d = getPocetVterin() / (double) naPocet[cisloJednotky];
    String s = df.format(d);
    if (stejne == true) {
      zaokrouhli(s);
    }
    else {
      if (s.indexOf(',') < 0  &&  s.indexOf('.') < 0) {
        DecimalFormat dfp = new DecimalFormat("#,###.######");
        s = dfp.format(d);
      }
      pocetTF.setText(s);
    }
  }

  private void aktualizujPocet() {
    int i = coJeNastaveno();
    if (i == 0  ||  i == 4) {
      // pro vteriny a tydny
      double d = getPocetVterin() / (double) naPocet[i];
      String s = df.format(d);
      pocetTF.setText(s);
    }
    else {
      // pro minuty, hodiny, mesice a roky
      presnyPocet(i);
    }
  }

  private int getPocet() {
    return Integer.parseInt(zaokrouhli());
  }

  private void aktualizujDatum() {
    int i = coJeNastaveno();
    Calendar cal = Calendar.getInstance();
    cal.setTime(narozeni.getCalendar().getTime());
    int pocet = getPocet();
    cal.add(naJednotky[i], pocet);
    oslava.nastavDatum(cal);
    oslava.vypisCas();
  }

  private long getPocetVterin() {
    long narozeni = this.narozeni.getVteriny();
    return this.oslava.getVteriny() - narozeni;
  }

  public void update(Observable o, Object arg) {
    aktualizujPocet();
  }

  private int coJeNastaveno() {
    return casovaJednotkaBG.getSelection().getMnemonic();
  }

  public static void main(String[] args) {
    JFrame okno = new JFrame("Víte, kdy slavit?");
    JApplet aplet = new Oslava();
    okno.getContentPane().add(aplet);
    aplet.init();
    okno.setLocation(100, 10);
    okno.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    okno.pack();
    okno.setVisible(true);
  }
}