
package uk.co.wingpath.modbusgui;

import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.util.concurrent.*;
import javax.swing.*;
import uk.co.wingpath.event.*;
import uk.co.wingpath.event.Event;
import uk.co.wingpath.io.*;
import uk.co.wingpath.util.*;
import uk.co.wingpath.gui.*;

public class TcpInterfacePanel
    implements SettingsSubPanel
{
    private final Frontend frontend;
    private final boolean toMaster;
    private final StatusBar statusBar;

    private WComponent<String> remoteHostField;
    private WComponent<Integer> remotePortField;
    private WComponent<String> localHostField;
    private WComponent<Integer> localPortField;
    private GridBagPanel panel;
    private final ValueEventSource listeners;

    public TcpInterfacePanel (Frontend frontend, boolean toMaster,
        StatusBar statusBar)
    {
        this.frontend = frontend;
        this.toMaster = toMaster;
        this.statusBar = statusBar;
        listeners = new ValueEventSource ();

        panel = new GridBagPanel ();

        ValueListener listener = new ValueListener ()
            {
                public void valueChanged (ValueEvent e)
                {
                    Event.checkIsEventDispatchThread ();
                    listeners.fireValueChanged (e);
                }
            };

        if (toMaster)
        {
            remoteHostField = new WTextField (statusBar, "Remote host", false);
            remotePortField = new WIntegerField (statusBar, "Remote port",
                0, TcpSettings.MAX_PORT, 0);

            localHostField = new WTextField (statusBar, "Host", true);
            localHostField.setToolTipText (
                "<html>Host name or IP address " +
                    "on which to accept connections.<br>" +
                    "Leave empty for any address." +
                "</html>");
            localHostField.setMnemonic (KeyEvent.VK_O);
            localHostField.setWidthChars (25);
            localHostField.addValueListener (listener);
            panel.addComponent (localHostField);

            localPortField = new WIntegerField (statusBar, "Port",
                TcpSettings.MIN_PORT, TcpSettings.MAX_PORT,
                TcpSettings.MIN_PORT);
            localPortField.setToolTipText ("Port number on which to listen");
            localPortField.setMnemonic (KeyEvent.VK_P);
            localPortField.setWidthChars (10);
            localPortField.addValueListener (listener);
            panel.addComponent (localPortField);
        }
        else
        {
            remoteHostField = new WTextField (statusBar, "Host", false);
            remoteHostField.setToolTipText ("Host name or IP address of slave");
            remoteHostField.setMnemonic (KeyEvent.VK_O);
            remoteHostField.setWidthChars (25);
            remoteHostField.addValueListener (listener);
            panel.addComponent (remoteHostField);

            remotePortField = new WIntegerField (statusBar, "Port",
                TcpSettings.MIN_PORT, TcpSettings.MAX_PORT,
                TcpSettings.MIN_PORT);
            remotePortField.setToolTipText ("Port number of slave");
            remotePortField.setMnemonic (KeyEvent.VK_P);
            remotePortField.setWidthChars (10);
            remotePortField.addValueListener (listener);
            panel.addComponent (remotePortField);

            localHostField = new WTextField (statusBar, "Local host", true);
            localHostField.setToolTipText (
                "<html>Host name or IP address of local interface to be<br>" +
                "used to make connection to slave.<br>" +
                "Leave empty for any interface." +
                "</html>");
            localHostField.setMnemonic (KeyEvent.VK_O);
            localHostField.setWidthChars (25);
            localHostField.addValueListener (listener);
            panel.addComponent (localHostField);

            localPortField = new WIntegerField (statusBar, "Local port",
                0, TcpSettings.MAX_PORT, 0);
            localPortField.setToolTipText (
                "<html>Local port to be used to make connection to slave.<br>" +
                "Set to 0 to allow dynamic allocation of the port.</html>");
            localPortField.setMnemonic (KeyEvent.VK_P);
            localPortField.setWidthChars (10);
            localPortField.addValueListener (listener);
            panel.addComponent (localPortField);
        }

        panel.addFiller ();
        panel.setBorder (BorderFactory.createEmptyBorder (5, 20, 0, 20));
    }

    public JPanel getPanel ()
    {
        return panel;
    }

    public boolean checkValues ()
    {
        return remoteHostField.checkValue () &&
            remotePortField.checkValue () &&
            localHostField.checkValue () &&
            localPortField.checkValue ();
    }

    public void getValuesFromModel (Object model)
    {
        TcpSettings tcpSettings = (TcpSettings) model;
        remoteHostField.setValue (tcpSettings.getRemoteHost ());
        remotePortField.setValue (tcpSettings.getRemotePort ());
        localHostField.setValue (tcpSettings.getLocalHost ());
        localPortField.setValue (tcpSettings.getLocalPort ());
    }

    public void putValuesToModel (Object model)
    {
        TcpSettings tcpSettings = (TcpSettings) model;
        tcpSettings.setRemoteHost (remoteHostField.getValue ().trim ());
        tcpSettings.setRemotePort (remotePortField.getValue ());
        tcpSettings.setLocalHost (localHostField.getValue ().trim ());
        tcpSettings.setLocalPort (localPortField.getValue ());
        tcpSettings.fireValueChanged ();
    }

    public boolean haveValuesChanged (Object model)
    {
        boolean changed = false;
        TcpSettings tcpSettings = (TcpSettings) model;
        if (remoteHostField.hasValueChanged (tcpSettings.getRemoteHost ()))
            changed = true;
        if (remotePortField.hasValueChanged (tcpSettings.getRemotePort ()))
            changed = true;
        if (localHostField.hasValueChanged (tcpSettings.getLocalHost ()))
            changed = true;
        if (localPortField.hasValueChanged (tcpSettings.getLocalPort ()))
            changed = true;
        return changed;
    }

    public String getName ()
    {
        return "TCP Socket";
    }

    public void setEnabled (boolean enabled, BackendState state)
    {
        Event.checkIsEventDispatchThread ();
        remotePortField.setEnabled (enabled && state.isStopped);
        remoteHostField.setEnabled (enabled && state.isStopped);
        localPortField.setEnabled (enabled && state.isStopped);
        localHostField.setEnabled (enabled && state.isStopped);
    }

    public void addValueListener (ValueListener l)
    {
        listeners.addListener (l);
    }

    public void removeValueListener (ValueListener l)
    {
        listeners.removeListener (l);
    }

    public String getTag ()
    {
        return "tcp";
    }
}


