import javax.swing.JPanel;
import javax.swing.JComponent;
import java.awt.GridLayout;
import java.awt.Color;

/** Diese Klasse stellt eine Uhr grafisch dar.
  * Wir werden diese Klasse im Laufe der Zeit
  * so ausbauen, dass sie analog und digital
  * darstellen und die Anzeige im Sekundentakt
  * aktualisieren kann.
  **/
public class SwingUhr extends JPanel 
  implements Steuerung,Runnable {

  /** Unsere DigitalAnzeige */
  private Anzeige digital;
  
  /** Unsere AnalogAnzeige */
  private Anzeige analog; 
  
  /** unser einfaches Systemzeit-Uhrwerk */
  private Uhrwerk systemZeit;
  
  /** Eine Referenz auf das gerade verwendete Anzeigen-Objekt */
  private JComponent aktuell;
  
  /** Dieser Thread ist fuer das aktualisieren zustaendig */
  private Thread unruh;
  
  /** Konstruktor.
    **/
  public SwingUhr() {
    // Erzeuge die Instanzen fuer Uhrwerk und Anzeige
    digital = new DigitalAnzeige();
    analog = new AnalogAnzeige(); 
    systemZeit = new Systemzeit();
    // Gehe sicher, dass das Uhrwerk gesetzt ist
    digital.setUhrwerk(systemZeit);
    analog.setUhrwerk(systemZeit); 
    // Leite die DigitalAnzeige an die Oberflaeche weiter
    setLayout(new GridLayout(1,1));
    setAnalog(); 
  }
  
  /** Diese Methode aktiviert die digitale Darstellung der
    * Uhrzeit.
    **/
  public void setDigital()
  {
    // Fall: Wir sind sowieso schon auf der digitalen Anzeige
    if (aktuell != null && aktuell.equals(digital))
      return;
    // Andernfalls loeschen wir die aktuelle Komponente und ersetzen
    // sie durch die Digitalanzeige
    if (aktuell != null)
      remove(aktuell);
    aktuell = (JComponent) digital;
    add(aktuell);
  }
  
  /** Diese Methode aktiviert die analoge Darstellung der
    * Uhrzeit.
    **/
  public void setAnalog()
  {
    // Fall: Wir sind sowieso schon auf der digitalen Anzeige
    if (aktuell != null && aktuell.equals(analog))
      return;
    // Andernfalls loeschen wir die aktuelle Komponente und ersetzen
    // sie durch die Digitalanzeige
    if (aktuell != null)
      remove(aktuell);
    aktuell = (JComponent) analog;
    add(aktuell);
  }
  
  /** Diese Methode signalisiert der Steuerung, dass
    * sie mit ihrer Arbeit beginnen soll.
    **/
  public void aktivieren() {
    // Falls schon ein Thread laeuft, beenden wir die Methode
    if (unruh != null)
      return;
    // Andernfalls erzeugen wir einen neuen Thread
    unruh = new Thread(this);
    unruh.start();
  }
  
  /** Diese Methode signalisiert der Steuerung, dass
    * sie ihre Arbeit jetzt beenden kann.
    **/
  public void beenden() {
    // Falls noch kein Thread existiert, beenden wir die Methode
    if (unruh == null)
      return;
    // Andernfalls beenden wir den Thread
    unruh.interrupt();
    unruh = null;
  }
  
  /** Zyklisches aktualisieren der Zeit, wird von inneren Threads
    * aufgerufen.
    **/
  public void run() {
    // Wir durchlaufen eine (beinahe) Endlos-Schleife
    while(!Thread.currentThread().isInterrupted()) {
      // Aktualisiere die Zeit 
      digital.zeigeZeit(); 
      analog.zeigeZeit();
      // Schlafe fuer 1000 Millisekunden
      try {
        Thread.sleep(1000);
      }
      catch(InterruptedException e) {
        Thread.currentThread().interrupt();
      }
    }
  }
  
  /** Setze die Farbe fuer den Vordergrund der Uhr */
  public void setForeground(Color c) {
    if (digital != null)
      ((JComponent)digital).setForeground(c);
    if (analog != null)
      ((JComponent)analog).setForeground(c);
    super.setForeground(c);
  }
  
  /** Setze die Farbe fuer den Hintergrund der Uhr */
  public void setBackground(Color c) {
    if (digital != null)
      ((JComponent)digital).setBackground(c);
    if (analog != null)
      ((JComponent)analog).setBackground(c);
    super.setBackground(c);
  }
  
  /** Frage die aktuelle Vordergrundfarbe ab */
  public Color getForeground() {
    if (aktuell != null) 
      return aktuell.getForeground();
    return super.getForeground();
  }
  
  /** Frage die aktuelle Hintergrundfarbe ab */
  public Color getBackground() {
    if (aktuell != null) 
      return aktuell.getBackground();
    return super.getForeground();
  }
 
  /** Diese Methode liefert genau dann true zurueck, wenn
    * die Uhr momentan auf analoges Display geschaltet ist.
    **/
  public boolean isAnalog() {
    return aktuell.equals(analog);
  }
}
