/*
 ** This file is part of Filius, a network construction and simulation software.
 ** 
 ** Originally created at the University of Siegen, Institute "Didactics of
 ** Informatics and E-Learning" by a students' project group:
 **     members (2006-2007): 
 **         André Asschoff, Johannes Bade, Carsten Dittich, Thomas Gerding,
 **         Nadja Haßler, Ernst Johannes Klebert, Michell Weyer
 **     supervisors:
 **         Stefan Freischlad (maintainer until 2009), Peer Stechert
 ** Project is maintained since 2010 by Christian Eibl <filius@c.fameibl.de>
 **         and Stefan Freischlad
 ** Filius is free software: you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
 ** the Free Software Foundation, either version 2 of the License, or
 ** (at your option) version 3.
 ** 
 ** Filius is distributed in the hope that it will be useful,
 ** but WITHOUT ANY WARRANTY; without even the implied
 ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 ** PURPOSE. See the GNU General Public License for more details.
 ** 
 ** You should have received a copy of the GNU General Public License
 ** along with Filius.  If not, see <http://www.gnu.org/licenses/>.
 */
package filius.gui.anwendungssicht;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import filius.software.clientserver.ClientBaustein;

/**
 * <p>
 * Diese Klasse stellt die Benutzungsoberflaeche fuer das Client-Programm einer einfachen Client-Server-Anwendung zur
 * Verfuegung.
 * </p>
 * <p>
 * Nachrichten von der Anwendung werden nach dem Beobachtermuster durch die Benachrichtigung der Beobachter angenommen
 * und verarbeitet.
 * </p>
 */
public class GUIApplicationClientBausteinWindow extends GUIApplicationWindow {

    private static final long serialVersionUID = 1L;

    /**
     * Textfeld fuer die Ausgabe gesendeter und empfangener Nachrichten sowie fuer Fehlermeldungen
     */
    private JTextArea taAusgabe;

    /**
     * Textfeld fuer die Adresse des Servers, zu dem die Verbindung hergestellt werden soll
     */
    private JTextField tfServerAdresse;

    /**
     * Textfeld zur Angabe des TCP-Ports, auf dem der Server auf eingehende Nachrichten wartet
     */
    private JTextField tfServerPort;

    /** Textbereich zur Eingabe der Nachrichten */
    private JTextArea taSenden;

    /** Schaltflaeche zum initiieren des Verbindungsaufbaus */
    private JButton btVerbinden;

    /**
     * Schaltflaeche zum Senden einer zuvor eingegebenen Nachricht
     */
    private JButton btSenden;

    /**
     * Standard-Konstruktor, der automatisch zur Erzeugung der graphischen Benutzungsoberflaeche fuer diese Anwendung
     * aufgerufen wird.
     */
    public GUIApplicationClientBausteinWindow(GUIDesktopPanel desktop, String appName) {
        super(desktop, appName);
        initialisiereKomponenten();
    }

    /** Methode zur Initialisierung der graphischen Komponenten */
    private void initialisiereKomponenten() {
        JScrollPane scrollPane;
        Box hauptBox;
        Box hBox;
        JLabel label;

        hauptBox = Box.createVerticalBox();
        hauptBox.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
        hauptBox.add(Box.createVerticalStrut(5));

        hBox = Box.createHorizontalBox();
        label = new JLabel(messages.getString("clientbaustein_msg1"));
        label.setPreferredSize(new Dimension(140, label.getHeight()));
        hBox.add(label);

        tfServerAdresse = new JTextField();
        tfServerAdresse.setPreferredSize(new Dimension(100, 20));
        hBox.add(tfServerAdresse);
        hauptBox.add(hBox);
        hauptBox.add(Box.createVerticalStrut(5));

        hBox = Box.createHorizontalBox();
        label = new JLabel(messages.getString("clientbaustein_msg2"));
        label.setPreferredSize(new Dimension(140, label.getHeight()));
        hBox.add(label);

        tfServerPort = new JTextField();
        tfServerPort.setPreferredSize(new Dimension(100, 20));
        hBox.add(tfServerPort);
        hauptBox.add(hBox);
        hauptBox.add(Box.createVerticalStrut(5));

        btVerbinden = new JButton(messages.getString("clientbaustein_msg3"));
        btVerbinden.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if (e.getActionCommand().equals("verbinden")) {
                    ((ClientBaustein) holeAnwendung()).setZielIPAdresse(tfServerAdresse.getText());
                    ((ClientBaustein) holeAnwendung()).setZielPort(Integer.parseInt(tfServerPort.getText()));
                    ((ClientBaustein) holeAnwendung()).verbinden();
                } else {
                    ((ClientBaustein) holeAnwendung()).trennen();
                }
                aktualisieren();
            }
        });
        hauptBox.add(btVerbinden);
        hauptBox.add(Box.createVerticalStrut(5));

        label = new JLabel(messages.getString("clientbaustein_msg4"));
        label.setPreferredSize(new Dimension(100, 20));
        hauptBox.add(label);

        taSenden = new JTextArea();
        scrollPane = new JScrollPane(taSenden);
        scrollPane.setPreferredSize(new Dimension(400, 50));
        hauptBox.add(scrollPane);

        btSenden = new JButton(messages.getString("clientbaustein_msg5"));
        btSenden.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                ((ClientBaustein) holeAnwendung()).senden(taSenden.getText());
                taSenden.setText("");
            }
        });
        hauptBox.add(btSenden);
        hauptBox.add(Box.createVerticalStrut(5));

        taAusgabe = new JTextArea();
        taAusgabe.setEditable(false);
        scrollPane = new JScrollPane(taAusgabe);
        scrollPane.setPreferredSize(new Dimension(400, 200));
        hauptBox.add(scrollPane);
        hauptBox.add(Box.createVerticalStrut(5));

        add(hauptBox, BorderLayout.CENTER);
        aktualisieren();
    }

    /**
     * Methode zum aktualisieren der Komponenten der graphischen Benutzungsoberflaeche in Abhaengigkeit vom Zustand der
     * Anwendung
     */
    private void aktualisieren() {
        ClientBaustein client;

        client = (ClientBaustein) holeAnwendung();

        tfServerAdresse.setText(client.getZielIPAdresse());
        tfServerPort.setText("" + client.getZielPort());
        if (client.istVerbunden()) {
            btVerbinden.setText(messages.getString("clientbaustein_msg6"));
            btVerbinden.setActionCommand("trennen");
            btSenden.setEnabled(true);

            tfServerAdresse.setEditable(false);
            tfServerPort.setEditable(false);
        } else {
            btVerbinden.setText(messages.getString("clientbaustein_msg3"));
            btVerbinden.setActionCommand("verbinden");
            btSenden.setEnabled(false);

            tfServerAdresse.setEditable(true);
            tfServerPort.setEditable(true);
        }
    }

    /**
     * Diese Methode wird automatisch ausgefuehrt, wenn eine Nachricht an den Beobachter der Anwendung gesendet wird.
     * Der Parameter arg enthaelt die Nachricht, die von der Anwendung verschickt wurde.
     */
    public void update(Observable o, Object arg) {
        if (arg != null) {
            this.taAusgabe.append(arg.toString() + "\n");
        }

        aktualisieren();
    }
}
