
package uk.co.wingpath.modbusgui;

import java.io.*;
import uk.co.wingpath.util.*;
import uk.co.wingpath.modbus.*;
import uk.co.wingpath.xml.*;
import uk.co.wingpath.event.*;

public class Settings
    implements Xml.Savable
{
    private final BigValueSettings bigValue;
    private final AddressSettings address;
    private final GeneralSettings general;
    private final InterfaceSettings slaveInterface;
    private final InterfaceSettings masterInterface;
    private final Registers registers;
    private final FileRegisters fileRegisters;
    private final DeviceIdSettings deviceId;
    private final LogSettings logging;
    private final CommandList commands;
    private final BooleanSettings columnVisibleSettings;
    private final BooleanSettings fileColumnVisibleSettings;
    private final boolean isTester;
    private final boolean debugging;

    public Settings (Product product, boolean debugging)
    {
        this.debugging = debugging;
        isTester = product.isTester ();
        bigValue = new BigValueSettings ();
        if (isTester)
        {
            registers = null;
            fileRegisters = null;
            address = null;
        }
        else
        {
            address = new AddressSettings ();
            registers = new Registers (bigValue.getValue (),
                address.getAddressMap ());
            fileRegisters = new FileRegisters (bigValue.getValue ());
            address.addValueListener (
                new ValueListener ()
                {
                    public void valueChanged (ValueEvent e)
                    {
                        registers.setAddressMap (address.getAddressMap ());
                    }
                });
            bigValue.addValueListener (
                new ValueListener ()
                {
                    public void valueChanged (ValueEvent e)
                    {
                        registers.setBigValueFlags (bigValue.getValue ());
                        fileRegisters.setBigValueFlags (bigValue.getValue ());
                    }
                });
        }
        commands = new CommandList ();

        if (product.hasSlaveMode ())
        {
            masterInterface = new InterfaceSettings (product, true);
        }
        else
        {
            masterInterface = null;
        }
        general = new GeneralSettings (product);
        slaveInterface = new InterfaceSettings (product, false);
        if (product.hasSlaveMode ())
            deviceId = new DeviceIdSettings (product);
        else
            deviceId = null;
        if (isTester)
        {
            columnVisibleSettings = null;
            fileColumnVisibleSettings = null;
        }
        else
        {
            columnVisibleSettings = new BooleanSettings ();
            fileColumnVisibleSettings = new BooleanSettings ();
        }
        logging = new LogSettings (debugging);
    }

    public Registers getRegisters ()
    {
        return registers;
    }

    public FileRegisters getFileRegisters ()
    {
        return fileRegisters;
    }

    public CommandList getCommands ()
    {
        return commands;
    }

    public GeneralSettings getGeneral ()
    {
        return general;
    }

    public BigValueSettings getBigValue ()
    {
        return bigValue;
    }

    public AddressSettings getAddress ()
    {
        return address;
    }

    public InterfaceSettings getSlaveInterface ()
    {
        return slaveInterface;
    }

    public InterfaceSettings getMasterInterface ()
    {
        return masterInterface;
    }

    public DeviceIdSettings getDeviceId ()
    {
        return deviceId;
    }

    public LogSettings getLogging ()
    {
        return logging;
    }

    public BooleanSettings getColumnVisible ()
    {
        return columnVisibleSettings;
    }

    public BooleanSettings getFileColumnVisible ()
    {
        return fileColumnVisibleSettings;
    }

    public void save (Xml.Saver saver)
        throws IOException
    {
        saver.startTag ("settings");
        saver.saveValue ("general", general);
        saver.saveValue ("bigvalues", bigValue);
        if (address != null)
            saver.saveValue ("address", address);
        saver.saveValue ("slaveinterface", slaveInterface);
        if (masterInterface != null)
            saver.saveValue ("masterinterface", masterInterface);
        if (columnVisibleSettings != null)
            saver.saveValue ("columns", columnVisibleSettings);
        if (fileColumnVisibleSettings != null)
            saver.saveValue ("filecolumns", fileColumnVisibleSettings);
        if (deviceId != null)
            saver.saveValue ("deviceid", deviceId);
        if (logging != null)
            saver.saveValue ("logging", logging);
        saver.endTag ("settings");

        if (registers != null)
            saver.saveValue ("registers", registers);
        if (fileRegisters != null)
            saver.saveValue ("fileregisters", fileRegisters);
        saver.saveValue ("commands", commands);
    }

    public Xml.Loader getXmlLoader (Reporter reporter)
    {
        if (reporter == null)
            throw new NullPointerException ("reporter must not be null");
        return new XmlLoader (reporter);
    }

    private class XmlLoader
        extends Xml.AbstractLoader
    {
        private final Reporter reporter;

        XmlLoader (Reporter reporter)
        {
            this.reporter = reporter;
        }

        public Xml.Loader startChild (String tag)
        {
            if (tag.equalsIgnoreCase ("settings"))
            {
                return new Xml.AbstractLoader ()
                {
                    public Xml.Loader startChild (String tag)
                    {
                        if (tag.equalsIgnoreCase ("general") || tag.equalsIgnoreCase ("master"))
                            return general.getXmlLoader ();
                        if (tag.equalsIgnoreCase ("bigvalues"))
                            return bigValue.getXmlLoader ();
                        if (address != null && tag.equalsIgnoreCase ("address"))
                            return address.getXmlLoader ();
                        if (tag.equalsIgnoreCase ("slaveinterface"))
                            return slaveInterface.getXmlLoader (reporter);
                        if (masterInterface != null &&
                            tag.equalsIgnoreCase ("masterinterface"))
                        {
                            return masterInterface.getXmlLoader (reporter);
                        }
                        if (columnVisibleSettings != null &&
                            tag.equalsIgnoreCase ("columns"))
                        {
                            return columnVisibleSettings.getXmlLoader ();
                        }
                        if (fileColumnVisibleSettings != null &&
                            tag.equalsIgnoreCase ("filecolumns"))
                        {
                            return fileColumnVisibleSettings.getXmlLoader ();
                        }
                        if (deviceId != null && tag.equalsIgnoreCase ("deviceid"))
                            return deviceId.getXmlLoader ();
                        if (logging != null && tag.equalsIgnoreCase ("logging"))
                            return logging.getXmlLoader ();
                        return null;
                    }
                };
            }
            if (registers != null && tag.equalsIgnoreCase ("registers"))
                return registers.getXmlLoader ();
            if (fileRegisters != null && tag.equalsIgnoreCase ("fileregisters"))
                return fileRegisters.getXmlLoader ();
            if (tag.equalsIgnoreCase ("commands"))
                return commands.getXmlLoader (isTester);
            return null;
        }
    }
}

