import javax.swing.*;
import java.awt.*;
import javax.swing.event.*;

/** Einfache Berechnung des Body-Mass-Index  */
public class BMI extends JPanel {
  
  // Verwendete grafische Komponenten
  JSlider alter = new JSlider(18,100,25);
  JSlider gewicht = new JSlider(40,200,75);
  JSlider groesse = new JSlider(120,210,175);
  JLabel label1 = new JLabel("Alter (in Jahren): ");
  JLabel label2 = new JLabel("Gewicht (in kg): ");
  JLabel label3 = new JLabel("Groesse (in cm): ");
  JLabel alterAktuell = new JLabel();
  JLabel gewichtAktuell = new JLabel();
  JLabel groesseAktuell = new JLabel();
  JLabel bmi = new JLabel(" ");
  JLabel warnung = new JLabel(" ");
  
  // Die Grenzen fuer Unter- und Uebergewicht 
  private final static int[][] GRENZEN =
    {{19,25,30},{19,27,30}};
    
  // Die Nachricht fuer die entsprechende Gewichtsgrenze
  private final static String[] WARNUNGEN =
  { "Laut BMI sind Sie untergewichtig. Bitte essen Sie mehr!",
    "Herzlichen Glueckwunsch! Bei Ihnen ist alles im Lot.",
    "Laut BMI sind Sie uebergewichtig. Bitte tun Sie etwas!",
    "Suchen Sie bitte einen Arzt auf!!!"
  };
  
  // Die Farben, in denen die Warnungen dargestellt werden sollen
  private final static Color[] FARBEN =
    {Color.RED,Color.GREEN,Color.YELLOW,Color.RED};
  
  /** Hilfsmethode fuer den Konstruktor: Setze das Design */
  private void setDesign() {
    // Einige Labels wollen sollen farbig sein -
    // hierzu muessen wir den opaque-"Schalter" setzen
    warnung.setOpaque(true);
    bmi.setOpaque(true);
    // Der Text in diesen Labeln soll ausserdem zentriert sein
    warnung.setHorizontalAlignment(SwingConstants.CENTER);
    bmi.setHorizontalAlignment(SwingConstants.CENTER);
    // Fuer unsere aktuell gesetzten Werte sollen die Zahlen nach
    // rechts ausgerichtet werden.
    alterAktuell.setHorizontalAlignment(SwingConstants.RIGHT);
    gewichtAktuell.setHorizontalAlignment(SwingConstants.RIGHT);
    groesseAktuell.setHorizontalAlignment(SwingConstants.RIGHT);
    // Verwende das GridBagLayout
    GridBagLayout gridbag = new GridBagLayout();
    setLayout(gridbag);
    GridBagConstraints constraints = new GridBagConstraints();
    // Das Layout soll keine "Luecken" hinterlassen, 
    // sondern alle Komponenten einer Spalte so weit strecken, 
    // dass sie gleich weit sind
    constraints.fill = GridBagConstraints.HORIZONTAL;
    // Setze die einzelnen Eingabefelder in einer Schleife
    JSlider[] sliders = {alter,gewicht,groesse};
    JLabel[] labels = {label1,label2,label3};
    JLabel[] aktuell = {alterAktuell,gewichtAktuell,groesseAktuell};
    for (int i = 0; i < 3; i++) {
      // Setze die Zeile, in der wir uns befinden
      constraints.gridy = i;
      // Setze den Label
      constraints.gridx = 0;
      gridbag.setConstraints(labels[i],constraints);
      this.add(labels[i]);
      // Setze den Slider
      constraints.gridx = 1;
      gridbag.setConstraints(sliders[i],constraints);
      this.add(sliders[i]);      
      // Setze die Darstellung der gesetzten Werte
      constraints.gridx = 2;
      gridbag.setConstraints(aktuell[i],constraints);
      this.add(aktuell[i]);
    }
    // Zu guter Letzt setze die Ergebnislabel - und mache
    // sie so breit wie das Fenster
    constraints.gridx = 0;
    constraints.gridy = 3;
    constraints.gridwidth = 3;
    gridbag.setConstraints(bmi,constraints);
    this.add(bmi);
    constraints.gridy = 4;
    gridbag.setConstraints(warnung,constraints);
    this.add(warnung);
  }

  /** Hilfsmethode fuer den Konstruktor: Setze benoetigte Listener */
  private void setListeners() {
    // Bei jedem Wechsel soll die setBMI-Methode aufgerufen werden.
    ChangeListener listener = new ChangeListener() {
      public void stateChanged(ChangeEvent e) {
        setBMI();
      }
    };
    alter.addChangeListener(listener);
    gewicht.addChangeListener(listener);
    groesse.addChangeListener(listener);
  }

  /** Diese Methode wird aufgerufen, 
    * wann immer ein Slider bewegt wird 
    **/
  private void setBMI() {
    // Aktualisiere die gesetzten Werte in den Labeln
    alterAktuell.setText(String.valueOf(alter.getValue()));
    gewichtAktuell.setText(String.valueOf(gewicht.getValue()));
    groesseAktuell.setText(String.valueOf(groesse.getValue()));
    // Berechne den BMI und setze das Label
    int berechnet = (int) Math.round(gewicht.getValue() / Math.pow(
      groesse.getValue() / 100.0, 2));
    bmi.setText("Laut diesen Angaben haben Sie einen BMI von " 
      + berechnet + ".");
    // Nun finde die Warnung, die zu diesem BMI passt
    int kategorie = alter.getValue() < 35 ? 0 : 1;
    int index = 0;
    for (; index < 3; index++)
      if (berechnet < GRENZEN[kategorie][index])
        break;
    // Setze den entsprechenden Text und die Farbe
    warnung.setText(WARNUNGEN[index]);
    warnung.setBackground(FARBEN[index]);
    bmi.setBackground(FARBEN[index]);
  }

  /** Konstruktor */
  public BMI() {
    setDesign();
    setListeners();
    setBMI();
  }
  
  /** Main-Methode */
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setTitle("BMI Rechner");
    frame.setContentPane(new BMI());
    frame.pack();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
  }
}
