/*
 * CellRenderer.java
 *
 * This class is responsible for rendering the cells in the 3 types of tables:
 *    crop, operations, process.
 *
 * Jim Frankenberger
 * USDA-ARS, West Lafayette IN
 * jrf@purdue.edu
 *
 * Created on August 20, 2004, 9:41 AM
 */
package ex1;

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

/**
 * This class is repsonsible for rendering the cells in the 3 types of tables:
 *    crop, operations, process.
 * @author  jrf
 */
public class CellRenderer extends JTextArea implements TableCellRenderer {

    private static final long serialVersionUID = 1L;

    private final Font theFont;
    /**
     * main model
     */
    private WepsTableModel wtm;

    /**
     * for detail process tables indicates which kind.
     */
    private final int modelTab;

    private final Color editedEntry = Color.GREEN;
    static final Color outsideRecommended = Color.YELLOW;
    static final Color outsideAbsolute = Color.MAGENTA;
    static final Color outofOrder = Color.RED;
    private final Color nameMismatch = Color.PINK;

    /** 
     * Creates a new instance of Class 
     * @param f Font to use, forces to be non-bold
     * @param id Identifying string, such as "CROP", "OPERATION"
     * @param mt Model tab for detail process tables, 0 for a main table
     */
    public CellRenderer(Font f, String id, int mt) {
        setOpaque(true);
        theFont = f;
        wtm = null;
        modelTab = mt;   // for detail process tables this will be > 0
    }

    /**
     * This is called automatically by the java framework.
     *
     * @param column
     * @param row
     * @param isSelected
     * @param hasFocus
     * @return 
     */
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column) {
        // Prevent the text from being bold
        Font f = getFont();
        if (f.isBold()) {
            setFont(theFont);
        }

        int rowOrig = row;

        if (value != null) {
            String s = value.toString();
            setText(s);
            if (s.startsWith("--")) {   // this indicates an empty cell in operations and detail tables
                if(!(table.getModel() instanceof FixedTableModel))
                {
                    if(((TableSorter2) table.getModel()).getTableModel() instanceof OpDetailTableModel)
                    {
                        OpDetailTableModel temp = ((OpDetailTableModel) 
                                ((TableSorter2) table.getModel()).getTableModel());
                        temp.setTableStatus(InputLimits.TableStatus.OKAY, row, column);
                        colorFrozenTable(table, row, rowOrig);
                    }
                }
                setBackground(Color.lightGray);
            } else {
                if (isSelected) { // highlight current cell
                    // Check data validation for Model when data format as integer or float
                    if (wtm != null && wtm.checkData) {
                        if(wtm instanceof CropTableModel)
                        {
                            validateDataCrop(row, column, s);
                        }
                        else if(wtm instanceof OprnTableModel)
                        {
                            validateDataOprn(row, column, s, table);
                        }
                    }
                    table.setRowSelectionInterval(row, row);
                    setBackground(table.getSelectionBackground());
                } else {

                    if (modelTab >= 0) {
                        // this row is coming from a detail table so we need to get the base row from
                        // the main operations model
                        row = wtm.getLogicalRow(modelTab, row);
                    }

                    WepsDBFile wf;
                    if (wtm.getType().equals(WepsTableModel.TableEnum.Crop)) {
                        wf = wtm.getXmlFile(row);  // get file attached to this row (one row per file for crop editor)
                        if (wtm.getColumnType(column) == ParamDef.ColumnType.STRING) {
                            setLineWrap(true);
                            setWrapStyleWord(true);
                        }
                    } else {
                        wf = null;
                    }

                    if(wtm instanceof OprnTableModel &&
                            table.getModel() instanceof TableSorter2)
                    {
                        if(((TableSorter2) table.getModel()).tableModel instanceof OpDetailTableModel)
                        {
                            colorFrozenTable(table, row, rowOrig);
			}
                        else
                        {
                            if (wtm != null && column == 1) {  // name column
                                if (wtm.isModified(row)) {
                                    // Changed data file name field is drawn in light blue
                                    setBackground(editedEntry);
                                } else if (wtm.nameMismatched(row)) {
                                    setBackground(nameMismatch);
                                } else if (wtm.outOfOrder(row)){
                                    setBackground(Color.RED);
                                }else {
                                    if (table.getSelectedRow() == rowOrig) {
                                        setBackground(table.getSelectionBackground());
                                    } else {
                                        setBackground(table.getBackground());
                                    }
                                }
                            } else {
                                if (table.getSelectedRow() == rowOrig) {
                                    setBackground(table.getSelectionBackground());
                                } else {
                                    setBackground(table.getBackground());
                                }
                            }
                        }
                    }
                    else
                    {
                        if (wtm != null && column == 1) {  // name column

                            if (wtm.isModified(row)) {
                                // Changed data file name field is drawn in light blue
                                setBackground(editedEntry);
                            } else if (wtm.nameMismatched(row)) {
                                setBackground(nameMismatch);
                            } else if (wtm.outOfOrder(row)) {
                                setBackground(Color.RED);
                            } else {
                                if (table.getSelectedRow() == rowOrig) {
                                    setBackground(table.getSelectionBackground());
                                } else {
                                    setBackground(table.getBackground());
                                }
                            }
                        } else {
                            if (table.getSelectedRow() == rowOrig) {
                                setBackground(table.getSelectionBackground());
                            } else {
                                setBackground(table.getBackground());
                            }
                        }
                    }

                    // Check data validation for Model when data format as integer or float
                    if (wtm != null && wtm.checkData) {
                        if(wtm instanceof CropTableModel)
                        {
                            validateDataCrop(row, column, s);
                        }
                        else if(wtm instanceof OprnTableModel)
                        {
                            validateDataOprn(row, column, s, table);
                        }
                    }
                            

                    if (wf != null) {
                        // if the file is read-only draw everything in gray
                        if (wf.isReadOnly()) {
                            setBackground(Color.lightGray);
                        }
                    }
                }
            }
        }

        return this;
    }

    /**
     * This validates that a specific cell is within the boundaries of the
     * limits defined by the corresponding Parameter Definition.
     * @param row
     * @param col
     * @param text 
     */
    private void validateDataCrop(int row, int col, String text) {
        // check that the column is of type float or int
        if (wtm.getColumnType(col) == ParamDef.ColumnType.FLOAT
                || wtm.getColumnType(col) == ParamDef.ColumnType.INTEGER) {
            DefnFileParser parms = wtm.getParamDef();
            if (col > 2 && !"???".equals(text)) {
                String value = text;
                String name = parms.getColumn(col - 3).name;
                InputLimits il = parms.getLimits(name);
                boolean altUnits = wtm.altUnits;
                ParamDef info = parms.getColumn(col - 3);
                if(altUnits) value = info.getAltRevValue(text);
                Double val = Double.parseDouble(value);
                boolean decomp = wtm.getXmlFile(row).getDecomp();
                InputLimits.TableStatus eval;
                if(decomp && !info.getDecomp()) eval = InputLimits.TableStatus.OKAY;
                else eval = il.evaluateInput(val);
                wtm.setTableStatus(eval, row, col);
                switch (eval) {
                    case NOSAVE:
                        setBackground(outsideAbsolute);
                        break;
                    case WARNSAVE:
                        setBackground(outsideRecommended);
                        break;
                    case OKAY:
                        break;
                    default:
                }
            }
        }
    }
    
    /**
     * This validates that a specific cell is within the boundaries of the
     * limits defined by the corresponding Parameter Definition.
     * 
     * Note:  Since this uses the operation table, we need to be updating the 
     * Operation Detail Models instead of the Operation Model, as the Operation
     * Detail Model can be used to set tab status as well.
     * 
     * Also, each table has a name.  The table with the null name is the initial
     * table, which we need to access data based upon the data inside.
     * @param row
     * @param col
     * @param text 
     */
    private void validateDataOprn(int row, int column, String value, JTable table)
    {
        String name = table.getName();
        if(name != null)
        {
            try
            {
                if (((OprnTableModel) wtm).getColumnTypeValidate(column, value) 
                        == ParamDef.ColumnType.FLOAT || ((OprnTableModel) wtm)
                        .getColumnTypeValidate(column, value) == ParamDef.ColumnType.INTEGER) {
                    DefnFileParser parms = wtm.getParamDef();
                    if (!"???".equals(value)) {
                        String text = value;
                        String paramName = parms.getColumn(column, name).name;
                        boolean altUnits = wtm.altUnits;
                        InputLimits il = parms.getLimits(paramName, name);
                        ParamDef info = parms.getColumn(column, name);
                        if(altUnits) text = info.getAltRevValue(value);
                        Double val = Double.parseDouble(text);
                        int tab = parms.getActionTab(name);
                        int xml = ((OprnTableModel) wtm).getLogicalRow(tab, row);
                        boolean decomp = wtm.getXmlFile(xml).getDecomp();
                        InputLimits.TableStatus eval;
                        if(decomp && !info.getDecomp()) eval = InputLimits.TableStatus.OKAY;
                        else eval = il.evaluateInput(val);
                        /**
                        * This line of code is to extract the OpDetailTableModel
                        * from the jTable.  The jTable's model is a TableSorter2,
                        * whose model in turn is a OpDetailTableModel, thus
                        * requiring the getModel from jtable, followed by a 
                        * type cast to TableSorter2 and another call to get Model
                        * and finally a type cast to OpDetailTableModel.
                        * phew.
                        */
                        OpDetailTableModel temp = ((OpDetailTableModel) 
                                ((TableSorter2) table.getModel()).getTableModel());
                        temp.setTableStatus(eval, row, column);
                        switch (eval) {
                            case NOSAVE:
                                setBackground(outsideAbsolute);
                                break;
                            case WARNSAVE:
                                setBackground(outsideRecommended);
                                break;
                            case OKAY:
                                break;
                            default:
                        }
                    }
                }
            }
            catch(NumberFormatException badstuff)
            {}
        }
        else
        {
            //The null table (Operation layout) has values of the style
            //"{ID} - {Value}
            String[] opSplit = value.split(" - ");
            if(opSplit.length != 1)
            {
                String opName = opSplit[1];
                WepsDBFile workingFile = wtm.getXmlFile(row);
                InputLimits.TableStatus eval = workingFile.getStatus(opName);
                wtm.setTableStatus(eval, row, column);
                switch (eval) {
                    case NOSAVE:
                        setBackground(outsideAbsolute);
                        break;
                    case WARNSAVE:
                        setBackground(outsideRecommended);
                        break;
                    case OKAY:
                        break;
                    default:
                }
            }
        }
    }

    /**
     *  Attach a JTable model to this renderer.
     *  @param ops Main table
     */
    public void setModel(WepsTableModel model) {
        wtm = model;
    }
    
    public void colorFrozenTable(JTable table, int row, int rowOrig)
    {
        DefnFileParser parms = wtm.getParamDef();
        String name = table.getName();
        int tab = 0;
        if(name != null) tab = parms.getActionTab(name);
        int xml = ((OprnTableModel) wtm).getLogicalRow(tab, row);
        if(wtm.isModified(xml) && wtm.nameMismatched(xml) && wtm.outOfOrder(xml))
        {
            OpDetailTableModel op = ((OpDetailTableModel) ((TableSorter2) table.getModel()).tableModel);
            op.getFrozenTable().addChangedRow(xml);
            op.getFrozenTable().addMismatchedRow(xml);
            op.getFrozenTable().addOutOfOrderRow(xml);
            if (table.getSelectedRow() == rowOrig) {
                setBackground(table.getSelectionBackground());
            } else {
                setBackground(table.getBackground());
            }
        } else if (wtm.isModified(xml) && wtm.nameMismatched(xml)) {
            // Changed data file name field is drawn in green
            OpDetailTableModel op = ((OpDetailTableModel) ((TableSorter2) table.getModel()).tableModel);
            op.getFrozenTable().addChangedRow(xml);
            op.getFrozenTable().addMismatchedRow(xml);
            op.getFrozenTable().removeOutOfOrderRow(xml);
            if (table.getSelectedRow() == rowOrig) {
                setBackground(table.getSelectionBackground());
            } else {
                setBackground(table.getBackground());
            }
        } else if (wtm.isModified(xml) && wtm.outOfOrder(xml)) {
            OpDetailTableModel op = ((OpDetailTableModel) ((TableSorter2) table.getModel()).tableModel);
            op.getFrozenTable().addChangedRow(xml);
            op.getFrozenTable().removeMismatchedRow(xml);
            op.getFrozenTable().addOutOfOrderRow(xml);
            if (table.getSelectedRow() == rowOrig) {
                setBackground(table.getSelectionBackground());
            } else {
                setBackground(table.getBackground());
            }
        } else if (wtm.nameMismatched(xml) && wtm.outOfOrder(xml)) {
            OpDetailTableModel op = ((OpDetailTableModel) ((TableSorter2) table.getModel()).tableModel);
            op.getFrozenTable().removeChangedRow(xml);
            op.getFrozenTable().addMismatchedRow(xml);
            op.getFrozenTable().addOutOfOrderRow(xml);
            if (table.getSelectedRow() == rowOrig) {
                setBackground(table.getSelectionBackground());
            } else {
                setBackground(table.getBackground());
            }
        } else if (wtm.isModified(xml)) {
            OpDetailTableModel op = ((OpDetailTableModel) ((TableSorter2) table.getModel()).tableModel);
            op.getFrozenTable().addChangedRow(xml);
            op.getFrozenTable().removeMismatchedRow(xml);
            op.getFrozenTable().removeOutOfOrderRow(xml);
            if (table.getSelectedRow() == rowOrig) {
                setBackground(table.getSelectionBackground());
            } else {
                setBackground(table.getBackground());
            }
        } else if (wtm.nameMismatched(xml)) {
            OpDetailTableModel op = ((OpDetailTableModel) ((TableSorter2) table.getModel()).tableModel);
            op.getFrozenTable().removeChangedRow(xml);
            op.getFrozenTable().addMismatchedRow(xml);
            op.getFrozenTable().removeOutOfOrderRow(xml);
            if (table.getSelectedRow() == rowOrig) {
                setBackground(table.getSelectionBackground());
            } else {
                setBackground(table.getBackground());
            }
        } else if (wtm.outOfOrder(xml)) {
            OpDetailTableModel op = ((OpDetailTableModel) ((TableSorter2) table.getModel()).tableModel);
            op.getFrozenTable().removeChangedRow(xml);
            op.getFrozenTable().removeMismatchedRow(xml);
            op.getFrozenTable().addOutOfOrderRow(xml);
            if (table.getSelectedRow() == rowOrig) {
                setBackground(table.getSelectionBackground());
            } else {
                setBackground(table.getBackground());
            }
        } else {
            if (table.getSelectedRow() == rowOrig) {
                OpDetailTableModel op = ((OpDetailTableModel) ((TableSorter2) table.getModel()).tableModel);
                op.getFrozenTable().removeChangedRow(xml);
                op.getFrozenTable().removeMismatchedRow(xml);
                setBackground(table.getSelectionBackground());
            } else {
                OpDetailTableModel op = ((OpDetailTableModel) ((TableSorter2) table.getModel()).tableModel);
                op.getFrozenTable().removeChangedRow(xml);
                op.getFrozenTable().removeMismatchedRow(xml);
                setBackground(table.getBackground());
            }
        }
        OpDetailTableModel op = ((OpDetailTableModel) ((TableSorter2) table.getModel()).tableModel);
        op.getFrozenTable().prepareRenderer(op.getFrozenTable().getCellRenderer(xml, 1), xml, 1);
        op.getFrozenTable().repaint();
    }
}
