
package uk.co.wingpath.modbusgui;

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

public class PollingSettingsPanel
    implements TreeCard
{
    private final Frontend frontend;

    private final Variable<Boolean> singleValue;
    private final Variable<Boolean> continuePolling;
    private final Variable<Integer> passDelay;

    private final WComponent<Boolean> singleValueCheckBox;
    private final WComponent<Boolean> continuePollingCheckBox;
    private final WComponent<Integer> passDelayField;

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

    public PollingSettingsPanel (Frontend frontend, Settings settings)
    {
        Event.checkIsEventDispatchThread ();
        this.frontend = frontend;
        statusListeners = new ValueEventSource ();

        GeneralSettings gs = settings.getGeneral ();
        singleValue = gs.getSingleValue ();
        continuePolling = gs.getContinuePolling ();
        passDelay = gs.getPassDelay ();

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

        outerPanel = new JPanel ();
        outerPanel.setLayout (new BorderLayout ());
        JLabel heading = Gui.createDialogHeading ("Polling");
        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);

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

        singleValueCheckBox = new WCheckBox ("Grouping", "Single Values",
            false);
        singleValueCheckBox.setToolTipText (
            "Whether to transfer values individually or in groups");
        singleValueCheckBox.setMnemonic (KeyEvent.VK_G);
        singleValueCheckBox.addValueListener (guiListener);
        panel.addComponent (singleValueCheckBox);

        continuePollingCheckBox = new WCheckBox ("Error Handling",
            "Continue Polling", false);
        continuePollingCheckBox.setToolTipText (
            "Whether to continue polling after error response from slave");
        continuePollingCheckBox.setMnemonic (KeyEvent.VK_E);
        continuePollingCheckBox.addValueListener (guiListener);
        panel.addComponent (continuePollingCheckBox);

        passDelayField = new WIntegerField (statusBar, "Pass Delay",
            GeneralSettings.MIN_PASS_DELAY,
            GeneralSettings.MAX_PASS_DELAY, 500);
        passDelayField.setToolTipText (
            "Delay (in milliseconds) between each pass through the registers");
        passDelayField.setMnemonic (KeyEvent.VK_P);
        passDelayField.setWidthChars (10);
        passDelayField.addValueListener (guiListener);
        panel.addComponent (passDelayField);

        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 ());

        frontend.addBackendStateListener (
            new BackendState.Listener ()
            {
                public void stateChanged (BackendState state)
                {
                    boolean en = state.isMaster;
                    singleValueCheckBox.setEnabled (en);
                    continuePollingCheckBox.setEnabled (en);
                    passDelayField.setEnabled (en);
                    setButtonsEnabled (en && hasUnappliedChanges ());
                }
            });

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

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

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

        getValuesFromModel ();
    }

    public JPanel getPanel ()
    {
        return outerPanel;
    }

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

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

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

    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 (singleValueCheckBox.hasValueChanged (singleValue.getValue ()))
            changed = true;
        if (continuePollingCheckBox.hasValueChanged (
            continuePolling.getValue ()))
        {
            changed = true;
        }
        if (passDelayField.hasValueChanged (passDelay.getValue ()))
            changed = true;
        return changed;
    }

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

    private boolean checkValues ()
    {
        return singleValueCheckBox.checkValue () &&
            continuePollingCheckBox.checkValue () &&
            passDelayField.checkValue ();
    }

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

    private void getValuesFromModel ()
    {
        statusBar.clear ();
        singleValueCheckBox.setValue (singleValue.getValue ());
        continuePollingCheckBox.setValue (continuePolling.getValue ());
        passDelayField.setValue (passDelay.getValue ());
        setButtonsEnabled (false);
    }

    private void putValuesToModel ()
    {
        singleValue.setValue (singleValueCheckBox.getValue ());
        continuePolling.setValue (continuePollingCheckBox.getValue ());
        passDelay.setValue (passDelayField.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);
    }
}


