
package uk.co.wingpath.modbusgui;

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

public class ExceptionField
    extends WAbstractComponent<ModbusException>
{
    private final JPanel panel;
    private final JLabel field;
    private final JButton button;
    private final Action helpAction;
    private ModbusException value;
    private final HelpViewer helpViewer;
    private String helpId;

    public ExceptionField (StatusBar statusBar, String label,
        final HelpViewer helpViewer)
    {
        this.helpViewer = helpViewer;
        value = null;
        helpId = null;

        panel = new JPanel ();
        panel.setLayout (new BoxLayout (panel, BoxLayout.X_AXIS));

        String exampleLine =
            "This_is_an_example_line_that_is_45_chars_long<br>";
        field = new JLabel ("<html>" + exampleLine + exampleLine + exampleLine);
        Dimension minSize = field.getMinimumSize ();
        field.setPreferredSize (minSize);
        field.setMaximumSize (minSize);
        panel.add (field);
        setText ();

        helpAction =
            new AbstractAction ("Error Help")
            {
                public void actionPerformed (ActionEvent e)
                {
                    Event.checkIsEventDispatchThread ();
                    if (helpViewer != null && helpId != null)
                        helpViewer.viewError (helpId);
                }
            };
        helpAction.putValue (Action.SHORT_DESCRIPTION,
            "Get help on this error message");
        panel.getActionMap ().put ("error_help", helpAction);

        button = new JButton (helpAction);
        button.setRequestFocusEnabled (false);
        panel.add (button);

        panel.setPreferredSize (
            new Dimension (minSize.width + 2, minSize.height + 2));
        setValue (null);

        initialize (panel, label);
    }

    private void setText ()
    {
        String msg = "";
        if (value != null)
        {
            int error = value.getErrorCode ();
            String explanation = value.getExplanation ();
            if (value.isResponse ())
            {
                msg = "Error response " + error + ": " +
                    Modbus.getErrorMessage (error);
            }
            else
            {
                if (error == Modbus.ERROR_NONE)
                {
                    msg = "OK";
                }
                else if (error == Modbus.ERROR_TIMED_OUT &&
                    explanation != null &&
                    explanation.equals ("Timed out"))
                {
                    msg = "Timed out";
                }
                else
                {
                    msg = value.getMessage ();
                }
            }
        }

        String [] lines = msg.split ("\n");
        msg = "<html>";

        for (int i = 0 ; i < lines.length ; i++)
        {
            if (i != 0)
                msg += "<br>";
            msg += lines [i];
        }

        if (lines.length == 1)
            msg += "<br>&nbsp;";

        field.setText (msg);
    }

    public ModbusException getValue ()
    {
        return value;
    }

    public void setValue (ModbusException value)
    {
        this.value = value;
        panel.removeAll ();
        panel.add (field);
        setText ();
        InputMap inputMap =
            panel.getInputMap (JComponent.WHEN_IN_FOCUSED_WINDOW);
        if (value != null && value.getHelpId () != null)
        {
            helpId = value.getHelpId ();
            panel.add (button);
            inputMap.put (KeyStroke.getKeyStroke (KeyEvent.VK_F4, 0),
                "error_help");
        }
        else
        {
            helpId = null;
            inputMap.remove (KeyStroke.getKeyStroke (KeyEvent.VK_F4, 0));
        }
        panel.revalidate ();
        panel.repaint ();
    }

    public void setValue (ModbusException value, boolean isError)
    {
        setValue (value);
        if (isError)
        {
            field.setOpaque (true);
            field.setBackground (Gui.COLOUR_BACKGROUND_ERROR);
        }
        else
        {
            field.setOpaque (false);
            field.setBackground (Gui.COLOUR_BACKGROUND_INACTIVE);
        }
    }
}

