
package uk.co.wingpath.modbusgui;

import java.io.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import uk.co.wingpath.event.*;
import uk.co.wingpath.util.*;
import uk.co.wingpath.modbus.*;
import uk.co.wingpath.gui.*;

public class TracingPanel
    implements TreeCard
{
    private final Variable<Boolean> intTrace;
    private final Variable<Boolean> rawTrace;
    private final Variable<Boolean> readTrace;
    private final Variable<Boolean> writeTrace;

    private final Frontend frontend;

    private final WComponent<Boolean> intTraceField;
    private final WComponent<Boolean> rawTraceField;
    private final WComponent<Boolean> readTraceField;
    private final WComponent<Boolean> writeTraceField;

    private final JButton applyButton;
    private final JButton resetButton;
    private final JPanel outerPanel;
    private final StatusBar statusBar;
    private final ValueEventSource statusListeners;

    public TracingPanel (Frontend frontend, Settings settings,
        boolean isTester)
    {
        this.frontend = frontend;
        GeneralSettings gs = settings.getGeneral ();
        statusListeners = new ValueEventSource ();

        intTrace = gs.getIntTraceSetting ();
        rawTrace = gs.getRawTraceSetting ();
        readTrace = gs.getReadTraceSetting ();
        writeTrace = gs.getWriteTraceSetting ();

        statusBar = new StatusBar ("tracing", frontend.getHelpViewer ());
        statusBar.addStatusListener (
            new ValueListener ()
            {
                public void valueChanged (ValueEvent e)
                {
                    fireStatusChanged ();
                }
            });

        outerPanel = new JPanel ();
        outerPanel.setLayout (new BorderLayout ());
        JLabel heading = Gui.createDialogHeading ("Tracing");
        outerPanel.add (heading, BorderLayout.NORTH);
        outerPanel.add (statusBar, BorderLayout.SOUTH);

        JPanel mainPanel = new JPanel ();
        outerPanel.add (mainPanel, BorderLayout.CENTER);
        mainPanel.setLayout (new BorderLayout ());
        ButtonPanel buttonPanel = new ButtonPanel ();
        mainPanel.add (buttonPanel, BorderLayout.SOUTH);

        GridBagPanel panel = new GridBagPanel ();
        mainPanel.add (panel, BorderLayout.CENTER);

        intTraceField = new WCheckBox ("Trace messages", intTrace.getValue ());
        intTraceField.setToolTipText ("Enable tracing of Modbus messages");
        intTraceField.setMnemonic (KeyEvent.VK_M);
        panel.addComponent (intTraceField);

        rawTraceField = new WCheckBox ("Trace raw data", rawTrace.getValue ());
        rawTraceField.setToolTipText (
            "Enable raw tracing of sent and received data");
        rawTraceField.setMnemonic (KeyEvent.VK_D);
        panel.addComponent (rawTraceField);

        readTraceField = new WCheckBox ("Trace values read",
            readTrace.getValue ());
        readTraceField.setToolTipText (
            "Enable tracing of register values read");
        readTraceField.setMnemonic (KeyEvent.VK_R);
        if (!isTester)
            panel.addComponent (readTraceField);

        writeTraceField = new WCheckBox ("Trace values written",
            writeTrace.getValue ());
        writeTraceField.setToolTipText (
            "Enable tracing of register values written");
        writeTraceField.setMnemonic (KeyEvent.VK_W);
        if (!isTester)
            panel.addComponent (writeTraceField);

        ValueListener guiListener =
            new ValueListener ()
            {
                public void valueChanged (ValueEvent e)
                {
                    statusBar.clear ();
                    setButtonsEnabled (hasUnappliedChanges ());
                }
            };

        intTraceField.addValueListener (guiListener);
        rawTraceField.addValueListener (guiListener);
        readTraceField.addValueListener (guiListener);
        writeTraceField.addValueListener (guiListener);

        applyButton = buttonPanel.addButton ("Apply", null,
            new ActionListener ()
            {
                public void actionPerformed (ActionEvent e)
                {
                    if (checkValues ())
                        putValuesToModel ();
                }
            });

        resetButton = buttonPanel.addButton ("Reset", null,
            new ActionListener ()
            {
                public void actionPerformed (ActionEvent e)
                {
                    reset ();
                }
            });
        resetButton.setMnemonic (KeyEvent.VK_R);

        buttonPanel.addButton (getHelpAction ());

        intTrace.addValueListener (
            new ValueListener ()
            {
                public void valueChanged (ValueEvent e)
                {
                    intTraceField.setValue (intTrace.getValue ());
                }
            });

        rawTrace.addValueListener (
            new ValueListener ()
            {
                public void valueChanged (ValueEvent e)
                {
                    rawTraceField.setValue (rawTrace.getValue ());
                }
            });

        readTrace.addValueListener (
            new ValueListener ()
            {
                public void valueChanged (ValueEvent e)
                {
                    readTraceField.setValue (readTrace.getValue ());
                }
            });

        writeTrace.addValueListener (
            new ValueListener ()
            {
                public void valueChanged (ValueEvent e)
                {
                    writeTraceField.setValue (writeTrace.getValue ());
                }
            });

        getValuesFromModel ();
    }

    public JPanel getPanel ()
    {
        return outerPanel;
    }

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

    public String getName ()
    {
        return "Tracing";
    }

    public Action getHelpAction ()
    {
        return frontend.getHelpAction ("tracing");
    }

    public JButton getDefaultButton ()
    {
        return applyButton;
    }

    public String getToolTipText ()
    {
        return null;
    }

    @Override
    public void selected ()
    {
    }

    @Override
    public void reset ()
    {
        getValuesFromModel ();
    }

    public boolean hasUnappliedChanges ()
    {
        boolean changed = false;
        if (intTraceField.hasValueChanged (intTrace.getValue ()))
            changed = true;
        if (rawTraceField.hasValueChanged (rawTrace.getValue ()))
            changed = true;
        if (readTraceField.hasValueChanged (readTrace.getValue ()))
            changed = true;
        if (writeTraceField.hasValueChanged (writeTrace.getValue ()))
            changed = true;
        return changed;
    }

    public boolean hasError ()
    {
        return statusBar.hasError ();
    }

    public boolean checkValues ()
    {
        return intTraceField.checkValue () &&
            rawTraceField.checkValue () &&
            readTraceField.checkValue () &&
            writeTraceField.checkValue ();
    }

    private void setButtonsEnabled (boolean enabled)
    {
        Gui.setEnabled (applyButton, enabled);
        Gui.setEnabled (resetButton, enabled);
        fireStatusChanged ();
    }

    public void getValuesFromModel ()
    {
        statusBar.clear ();
        intTraceField.setValue (intTrace.getValue ());
        rawTraceField.setValue (rawTrace.getValue ());
        readTraceField.setValue (readTrace.getValue ());
        writeTraceField.setValue (writeTrace.getValue ());
        setButtonsEnabled (false);
    }

    public void putValuesToModel ()
    {
        intTrace.setValue (intTraceField.getValue ());
        rawTrace.setValue (rawTraceField.getValue ());
        readTrace.setValue (readTraceField.getValue ());
        writeTrace.setValue (writeTraceField.getValue ());
        setButtonsEnabled (false);
    }

    private void fireStatusChanged ()
    {
        statusListeners.fireValueChanged (this);
    }

    public void addStatusListener (ValueListener l)
    {
        statusListeners.addListener (l);
    }

    public void removeStatusListener (ValueListener l)
    {
        statusListeners.removeListener (l);
    }
}


