
package uk.co.wingpath.modbusgui;

import javax.swing.table.*;
import java.awt.EventQueue;
import uk.co.wingpath.util.*;
import uk.co.wingpath.gui.*;

public abstract class CommandTableModel
    extends AbstractTableModel
{
    protected final int COL_FILE;
    protected final int COL_ADDRESS;
    protected final int COL_EXPECTED;
    protected final int COL_ACTUAL;
    protected final boolean isTester;
    protected final boolean isEditor;
    protected final boolean isWrite;
    protected final boolean isFile;
    private final int columnCount;
    private boolean expectedEnabled;

    /**
    * Constructs a CommandTableModel.
    * @param isTester true if the table has "Expected" and "Actual" value
      columns (i.e. the table is for a read command in ModTest), false if it
      has a single "Value" column.
    * @param isEditor true if the table is in an editing panel that highlights
      unapplied changes.
    * @param isWrite true if the table is for a write command and the "Value"
      column is therefore editable. Ignored if isTester is true.
    * @param isFile true if the table has a column for the file number.
    */
    public CommandTableModel (boolean isTester, boolean isEditor,
        boolean isWrite, boolean isFile)
    {
        this.isTester = isTester;
        this.isEditor = isEditor;
        this.isWrite = isWrite;
        this.isFile = isFile;
        if (isFile)
        {
            COL_FILE = 0;
            COL_ADDRESS = 1;
            if (isTester)
            {
                COL_EXPECTED = 2;
                COL_ACTUAL = 3;
            }
            else
            {
                COL_ACTUAL = 2;
                COL_EXPECTED = -1;
            }
        }
        else
        {
            COL_FILE = -1;
            COL_ADDRESS = 0;
            if (isTester)
            {
                COL_EXPECTED = 1;
                COL_ACTUAL = 2;
            }
            else
            {
                COL_ACTUAL = 1;
                COL_EXPECTED = -1;
            }
        }
        columnCount = isFile ? (isTester ? 4 : 3) : (isTester ? 3 : 2);
        expectedEnabled = true;
    }

    @Override
    public int getColumnCount ()
    {
        return columnCount;
    }

    @Override
    public String getColumnName (int col)
    {
        if (col == COL_FILE)
            return "File";
        if (col == COL_ADDRESS)
            return "Address";
        if (col == COL_EXPECTED)
            return "Expected";
        if (col == COL_ACTUAL)
            return isTester ? "Actual" : "Value";
        return "";
    }

    public int getColumnWidth (int col)
    {
        if (col == COL_ACTUAL || col == COL_EXPECTED)
            return Gui.getTextWidth (17);
        return Gui.getTextWidth (getColumnName (col));
    }

    @Override
    public Class getColumnClass (int col)
    {
        return String.class;
    }

    @Override
    public boolean isCellEditable (int row, int col)
    {
        if (isTester)
        {
            return col == COL_EXPECTED && expectedEnabled;
        }
        else
        {
            return col == COL_ACTUAL && isWrite;
        }
    }

    public void enableExpected (boolean enable)
    {
        expectedEnabled = enable;
    }

    public abstract String fromString (String value, int row, int col)
        throws ValueException;

    public abstract boolean isError (int row, int col);
    public abstract boolean isUnapplied (int row, int col);
    public abstract boolean haveActualValuesChanged (Numeric.Value [] values);
    public abstract boolean haveExpectedValuesChanged (
        Numeric.PatVal [] values);
    // public abstract Numeric.Pattern [] getExpectedData ();
    // public abstract Numeric.Value [] getActualData ();
}

