
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.*;
import uk.co.wingpath.xml.*;

public class UdpSettings
    implements Xml.Savable
{
    public static final int MIN_PORT = 1;
    public static final int MAX_PORT = 65535;

    private final boolean toMaster;
    private String remoteHost;
    private int remotePort;
    private String localHost;
    private int localPort;
    private final ValueEventSource listeners;

    public UdpSettings (boolean toMaster)
    {
        this.toMaster = toMaster;
        if (toMaster)
        {
            remoteHost = "";
            remotePort = 0;
            localHost = "localhost";
            localPort = 502;
        }
        else
        {
            remoteHost = "localhost";
            remotePort = 502;
            localHost = "";
            localPort = 0;
        }
        listeners = new ValueEventSource ();
    }

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

    public String getRemoteHost ()
    {
        return remoteHost;
    }

    public void setRemoteHost (String remoteHost)
    {
        if (!remoteHost.equals (this.remoteHost))
        {
            this.remoteHost = remoteHost;
            // Caller should call fireValueChanged after setting all values
            // listeners.fireValueChanged (this);
        }
    }

    public int getRemotePort ()
    {
        return remotePort;
    }

    public void setRemotePort (int remotePort)
    {
        if (remotePort != this.remotePort)
        {
            this.remotePort = remotePort;
            // Caller should call fireValueChanged after setting all values
            // listeners.fireValueChanged (this);
        }
    }

    public String getLocalHost ()
    {
        return localHost;
    }

    public void setLocalHost (String localHost)
    {
        if (!localHost.equals (this.localHost))
        {
            this.localHost = localHost;
            // Caller should call fireValueChanged after setting all values
            // listeners.fireValueChanged (this);
        }
    }

    public int getLocalPort ()
    {
        return localPort;
    }

    public void setLocalPort (int localPort)
    {
        if (localPort != this.localPort)
        {
            this.localPort = localPort;
            // Caller should call fireValueChanged after setting all values
            // listeners.fireValueChanged (this);
        }
    }

    public UdpConnection createConnection (Reporter reporter)
    {
        return new UdpConnection (remoteHost, remotePort,
            localHost, localPort, reporter);
    }

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

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

    public void fireValueChanged ()
    {
        listeners.fireValueChanged (this);
    }

    public void save (Xml.Saver saver)
        throws IOException
    {
        if (!toMaster)
        {
            saver.saveValue ("remotehost", remoteHost);
            saver.saveValue ("remoteport", remotePort);
        }
        saver.saveValue ("localhost", localHost);
        saver.saveValue ("localport", localPort);
    }

    public Xml.Loader getXmlLoader ()
    {
        return new XmlLoader ();
    }

    private class XmlLoader
        extends Xml.AbstractLoader
    {
        @Override
        public Xml.Loader startChild (String tag)
        {
            if (tag.equalsIgnoreCase ("remotehost"))
            {
                return new Xml.StringLoader (new Xml.Receiver<String>()
                {
                    public void receive (String value)
                    {
                        remoteHost = value;
                    }
                });
            }

            if (tag.equalsIgnoreCase ("remoteport"))
            {
                return new Xml.IntegerLoader (MIN_PORT, MAX_PORT,
                    new Xml.Receiver<Integer> ()
                    {
                        public void receive (Integer value)
                        {
                            remotePort = value;
                        }
                    });
            }

            if (tag.equalsIgnoreCase ("localhost"))
            {
                return new Xml.StringLoader (new Xml.Receiver<String>()
                {
                    public void receive (String value)
                    {
                        localHost = value;
                    }
                });
            }

            if (tag.equalsIgnoreCase ("localport"))
            {
                return new Xml.IntegerLoader (toMaster ? MIN_PORT : 0, MAX_PORT,
                    new Xml.Receiver<Integer> ()
                    {
                        public void receive (Integer value)
                        {
                            localPort = value;
                        }
                    });
            }

            if (tag.equalsIgnoreCase ("host"))
            {
                return new Xml.StringLoader (new Xml.Receiver<String>()
                {
                    public void receive (String value)
                    {
                        if (toMaster)
                            localHost = value;
                        else
                            remoteHost = value;
                    }
                });
            }

            if (tag.equalsIgnoreCase ("port"))
            {
                return new Xml.IntegerLoader (MIN_PORT, MAX_PORT,
                    new Xml.Receiver<Integer> ()
                    {
                        public void receive (Integer value)
                        {
                            if (toMaster)
                                localPort = value;
                            else
                                remotePort = value;
                        }
                    });
            }

            return null;
        }

        @Override
        public void cleanup ()
        {
            fireValueChanged ();
        }
    }
}


