
package uk.co.wingpath.modbusgui;

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

public class Command22Panel
    implements CommandPanel
{
    private final Frontend frontend;
    private final Settings settings;
    private final ValueEventSource listeners;
    private final boolean isTester;
    private final boolean isEditor;

    private final StatusBar statusBar;
    private final GridBagPanel panel;
    private final WNumericField orMaskField;
    private final WNumericField andMaskField;
    private final RadixSelector radixSelector;
    private final WComponent<Integer> addressField;
    private final TypeSelector typeSelector;
    private final WComponent<Integer> slaveIdField;

    private CommandResult actualResult;

    public Command22Panel (Frontend frontend, Settings settings,
        final StatusBar statusBar, MirrorField mirror, boolean isTester, boolean isEditor)
    {
        Event.checkIsEventDispatchThread ();
        this.frontend = frontend;
        this.settings = settings;
        this.statusBar = statusBar;
        this.isTester = isTester;
        this.isEditor = isEditor;
        listeners = new ValueEventSource ();
        actualResult = null;

        panel = new GridBagPanel ();
        panel.addTitle (Command22.typeName);

        int slaveId = settings.getGeneral ().getSlaveId ().getValue ();
        slaveIdField = new WIntegerField (statusBar, "Slave ID",
            0, 255, slaveId);
        slaveIdField.setToolTipText ("Slave identifier");
        slaveIdField.setWidthChars (4);
        slaveIdField.setMnemonic (KeyEvent.VK_I);
        slaveIdField.setMirror (mirror);
        panel.addComponent (slaveIdField);

        addressField = new WIntegerField (statusBar, "Address", 0, 65535, 0);
        addressField.setToolTipText ("Address of register");
        addressField.setWidthChars (8);
        addressField.setMnemonic (KeyEvent.VK_A);
        addressField.setMirror (mirror);
        panel.addComponent (addressField);

        typeSelector = TypeSelector.create (true, false);
        typeSelector.setValue (Numeric.Type.uint16);
        panel.addComponent (typeSelector);

        radixSelector = new RadixSelector (false);
        radixSelector.setRadix (16);
        panel.addComponent (radixSelector);

        andMaskField = new WNumericField (statusBar, "And Mask");
        andMaskField.setType (typeSelector.getValue ());
        andMaskField.setRadix (radixSelector.getValue ());
        andMaskField.setToolTipText ("And Mask");
        andMaskField.setWidthChars (10);
        andMaskField.setMnemonic (KeyEvent.VK_M);
        andMaskField.setMirror (mirror);
        panel.addComponent (andMaskField);

        orMaskField = new WNumericField (statusBar, "Or Mask");
        orMaskField.setType (typeSelector.getValue ());
        orMaskField.setRadix (radixSelector.getValue ());
        orMaskField.setToolTipText ("Or Mask");
        orMaskField.setWidthChars (10);
        orMaskField.setMnemonic (KeyEvent.VK_O);
        orMaskField.setMirror (mirror);
        panel.addComponent (orMaskField);

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

        slaveIdField.addValueListener (listener);

        typeSelector.addValueListener (new ValueListener ()
        {
            public void valueChanged (ValueEvent e)
            {
                Event.checkIsEventDispatchThread ();
                if (!e.isChanging ())
                {
                    Numeric.Type type = typeSelector.getValue ();
                    andMaskField.setType (type);
                    orMaskField.setType (type);
                }
                listeners.fireValueChanged (e);
            }
        });

        radixSelector.addValueListener (new ValueListener ()
        {
            public void valueChanged (ValueEvent e)
            {
                Event.checkIsEventDispatchThread ();
                if (!e.isChanging ())
                {
                    int radix = radixSelector.getValue ();
                    andMaskField.setRadix (radix);
                    orMaskField.setRadix (radix);
                }
                listeners.fireValueChanged (e);
            }
        });

        addressField.addValueListener (listener);
        andMaskField.addValueListener (listener);
        orMaskField.addValueListener (listener);
    }

    public JPanel getPanel ()
    {
        return panel;
    }

    public String getTitle ()
    {
        return Command22.typeName;
    }

    public String getTag ()
    {
        return Command22.tag;
    }

    public String getName ()
    {
        return "22 Mask Write Register";
    }

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

    public void initialize ()
    {
    }

    @Override
    public void setEnabled (boolean enabled, boolean enExpected)
    {
        slaveIdField.setEnabled (enabled);
        typeSelector.setEnabled (enabled);
        radixSelector.setEnabled (enabled);
        addressField.setEnabled (enabled);
        andMaskField.setEnabled (enabled);
        orMaskField.setEnabled (enabled);
    }

    @Override
    public void highlightErrors (boolean highlight)
    {
    }

    public boolean checkFields ()
    {
        Event.checkIsEventDispatchThread ();
        if (!slaveIdField.checkValue ())
            return false;
        if (!typeSelector.checkValue ())
            return false;
        if (!radixSelector.checkValue ())
            return false;
        if (!addressField.checkValue ())
            return false;
        if (!andMaskField.checkValue ())
            return false;
        if (!orMaskField.checkValue ())
            return false;
        return true;
    }

    public void setSlaveId (int slaveId)
    {
        slaveIdField.setValue (slaveId);
    }

    public void setCommand (Command command)
    {
        if (command == null)
        {
            int slaveId = settings.getGeneral ().getSlaveId ().getValue ();
            slaveIdField.setValue (slaveId);
            addressField.setValue (0);
            final Numeric.Type type = Numeric.Type.uint16;
            typeSelector.setValue (type);
            andMaskField.setType (type);
            orMaskField.setType (type);
            final int radix = 10;
            radixSelector.setValue (radix);
            andMaskField.setRadix (radix);
            orMaskField.setRadix (radix);
            andMaskField.setValue (type.zero);
            orMaskField.setValue (type.zero);
        }
        else
        {
            Command22 cmd = (Command22) command;
            slaveIdField.setValue (cmd.getSlaveId ());
            addressField.setValue (cmd.getAddress ());
            typeSelector.setValue (cmd.getType ());
            andMaskField.setType (cmd.getType ());
            orMaskField.setType (cmd.getType ());
            radixSelector.setValue (cmd.getRadix ());
            andMaskField.setRadix (cmd.getRadix ());
            orMaskField.setRadix (cmd.getRadix ());
            andMaskField.setValue (cmd.getAndMask ());
            orMaskField.setValue (cmd.getOrMask ());
        }
    }

    public void setActualResult (Command.Result result)
    {
        actualResult = (CommandResult) result;
        if (result != null)
        {
            ModbusException exception = result.getException ();
            if (exception != null)
                statusBar.showException (exception);
        }
    }

    @Override
    public void expectActual ()
    {
    }

    public Command22 createCommand (String name, String description,
        ModbusException exception)
    {
        Command22 cmd;
        if (isTester)
        {
            cmd = new Command22 (name,
                description,
                slaveIdField.getValue (),
                addressField.getValue (),
                typeSelector.getValue (),
                radixSelector.getValue (),
                orMaskField.getValue (),
                andMaskField.getValue (),
                exception);
        }
        else
        {
            cmd = new Command22 (name,
                description,
                slaveIdField.getValue (),
                addressField.getValue (),
                typeSelector.getValue (),
                radixSelector.getValue (),
                orMaskField.getValue (),
                andMaskField.getValue ());
        }
        cmd.setActualResult (actualResult);
        return cmd;
    }

    public boolean haveValuesChanged (Command command)
    {
        boolean changed = false;
        Command22 cmd = (Command22) command;
        if (slaveIdField.hasValueChanged (cmd.getSlaveId ()))
            changed = true;
        if (addressField.hasValueChanged (cmd.getAddress ()))
            changed = true;
        if (typeSelector.hasValueChanged (cmd.getType ()))
            changed = true;
        if (radixSelector.hasValueChanged (cmd.getRadix ()))
            changed = true;
        if (orMaskField.hasValueChanged (cmd.getOrMask ()))
            changed = true;
        if (andMaskField.hasValueChanged (cmd.getAndMask ()))
            changed = true;
        return changed;
    }

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

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


