/*
 * WepsTableDataView.java
 *
 * Created on June 9, 2006, 10:07 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package usda.weru.util.table;

import com.klg.jclass.table.EditableTableDataModel;
import com.klg.jclass.table.JCCellDisplayEvent;
import com.klg.jclass.table.JCCellDisplayListener;
import com.klg.jclass.table.JCTableDataEvent;
import com.klg.jclass.table.JCTableDataListener;
import com.klg.jclass.table.TableDataModel;
import com.klg.jclass.table.TableDataView;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
 *
 * @author Joseph Levin
 */
public class WepsTableDataView extends TableDataView implements  JCCellDisplayListener, MouseListener{
    private List <String> c_columnKeyMap;
    private boolean quickplot;
    /**
     * Creates a new instance of WepsTableDataView
     */
    public WepsTableDataView() {
        super();        
        init();
    }
    
    protected void setQuickPlot(boolean quickplot){
        this.quickplot = quickplot;            
        
    }
    
    protected boolean isQuickPlot(){
        return quickplot;
    }

    @Override
    public boolean isEditable() {        
        return quickplot || super.isEditable();       
    }
    
    
    
    private void init(){
    }
    
    /**
     * Return the index of the Column with the specified key.
     * @param key The key of the desired column.
     * @return The index of the desired Column.
     */
    public int getDataColumnIndex(String key){
        if (c_columnKeyMap == null){
            createColumnKeyMap();
        }
        return c_columnKeyMap.indexOf(key);
    }
    
    private void createColumnKeyMap(){
        //c_columnKeyMap = new ArrayList <String> ();
        c_columnKeyMap = new Vector <String> ();
        for (int i = 0; i < dataSource.getNumColumns(); i++){
            c_columnKeyMap.add(dataSource.getTableColumnLabel(i).toString());
        }
    }
    
    /**
     *
     * @param rowIndex
     * @param column
     * @return
     */
    public Object getObject(int rowIndex, Column column){
        return getObject(rowIndex, column.getId());
    }
    
    /**
     *
     * @param rowIndex
     * @param key
     * @return
     */
    public Object getObject(int rowIndex, String key){
        int columnIndex = getDataColumnIndex(key);
        if (columnIndex == -1){
            return null;
        }
        return super.getObject(rowIndex, columnIndex);
    }
    
    /**
     *
     * @param rowIndex
     * @param columnIndex
     * @return
     */
    public Object getObject(int rowIndex, int columnIndex){
        if(isQuickPlotRow(rowIndex)){
            if(columnIndex >= getTable().getFrozenColumns()){
                return getMeta().getColumn(columnIndex).isQuickPlot();
            }
            else{
                return null;
            }
            
        }
//        else if (isQuickPlot()){
//            rowIndex--;
//        }
        
        if (isLabelRow(rowIndex)){                 
            //Move -1 --> 0
            rowIndex = rowIndex + 1;
            return getMeta().getColumnLabel(getTable(), rowIndex, columnIndex);
            
        }
        if (columnIndex < 0 && rowIndex >= getMeta().getLabelRowCount() - 1){
            return super.getObject(rowIndex, columnIndex);
        }
        
        Column column = getMeta().getColumn(getDataColumn(columnIndex));
        if (column == null) return null;
        String dataKey = column.getDataKey();
        columnIndex = getDataColumnIndex(dataKey);
        if (columnIndex == -1){
            return null;
        }
        return super.getObject(rowIndex, columnIndex);
    }
    
    /**
     *
     * @param columnIndex
     * @return
     */
    public Object getTableColumnLabel(int columnIndex) {
        if (columnIndex < 0){
            return columnIndex;
        }
        Column column = getMeta().getColumn(columnIndex);
        return column.getName();
    }
    
    /**
     *
     * @param rowIndex
     * @return
     */
    public Object getTableRowLabel(int rowIndex){
        return rowIndex;
    }
    
    
    /**
     *
     * @param model
     */
    public void setDataSource(TableDataModel model) {
        TableDataModel wrapped = new DataSourceWrapper(model, this);
        super.setDataSource(wrapped);
        //super.setDataSource(model);
    }
    
    private WepsTableMeta getMeta(){
        return ((WepsTable) table).getMeta();
    }
    
    /**
     *
     * @param table
     */
    public void setTable(WepsTable table){
        if(getTable() != null){
            table.removeMouseListener(this);
        }
        super.setTable(table);
        table.addCellDisplayListener(this);
        table.addMouseListener(this);
    }
    
    /**
     *
     * @return
     */
    public WepsTable getTable(){
        return (WepsTable) table;
    }
    
    /**
     *
     * @return
     */
    public int getNumColumns() {
        return getMeta().getColumnCount();
    }
    
    /**
     *
     * @param rowIndex
     * @return
     */
    public boolean isLabelRow(int rowIndex){
        int numberOfLabelRows = getMeta().getLabelRowCount();
        if(quickplot){
            numberOfLabelRows++;
        }
        rowIndex = rowIndex + 1;    //-1 --> 0
        return (rowIndex < numberOfLabelRows);
    }
    
    public boolean isQuickPlotRow(int rowIndex){
        return quickplot && rowIndex == getMeta().getLabelRowCount() - 1 ;
    }
    /**
     *
     * @param event
     */
    public void cellDisplay(JCCellDisplayEvent event){
        prepareCellDisplay(event, WepsTableEnum.PREPARE_all);
    }
    
    /**
     *
     * @param event
     * @param flags
     */
    public void prepareCellDisplay(JCCellDisplayEvent event, int flags){
        int rowIndex = event.getRow();
        int columnIndex = event.getColumn();
        String unitsSystem = getTable().getUnitsSystem();
        Object o = event.getCellData();
        if (o instanceof String){
            o = getMeta().parse((String) o, getTable(), rowIndex, columnIndex);
        }
        if (isLabelRow(rowIndex)) return;
        
        //Else we actually update the data.
        Column column = getMeta().getColumn(columnIndex);
        if (column == null) return;
        if (Helper.bitFlag(flags, WepsTableEnum.PREPARE_adjustments)){
            o = column.applyAdjustments(o, unitsSystem);
        }
        
        if (Helper.bitFlag(flags, WepsTableEnum.PREPARE_displayunits)){
            o = column.applyDisplayUnits(o, unitsSystem);
        }
        
        if (Helper.bitFlag(flags, WepsTableEnum.PREPARE_limits)){
            o = column.applyLimits(o, unitsSystem);
        }
        
        if (Helper.bitFlag(flags, WepsTableEnum.PREPARE_formats)){
            o = column.applyFormat(o, unitsSystem);
        }
        
        event.setDisplayData(o);
    }
    
    
    
    /**
     *
     * @return
     */
    public int getNumRows(){
        return getMeta().getLabelRowCount() + super.getNumRows() + (isQuickPlot() ? 0 : -1);
    }
    
    /**
     *
     * @return
     */
    public String getUnitsSystem(){
        return getTable().getUnitsSystem();
    }
    
    protected FilteredDataSource c_filteredDataSource;
    protected List <ColumnFilter> c_columnFilters;
    
    /**
     *
     * @param filters
     */
    public void addColumnFilter(ColumnFilter... filters){
        if (c_columnFilters == null){
            c_columnFilters = new ArrayList <ColumnFilter> ();
        }
        for (ColumnFilter filter : filters){
            c_columnFilters.add(filter);
        }
        updateColumnFilters();
    }
    
    public void clearColumnFilters(){
        if (c_columnFilters != null){
            c_columnFilters.clear();
        }
        updateColumnFilters();
    }
    
    private void updateColumnFilters(){
        for (int ci = 0; ci < getMeta().getColumnCount(); ci++){
            Column column = getMeta().getColumn(ci);
            
            if(column.isHidden()) continue;
            
            boolean status = !getTable().isColumnHidden(ci);
            boolean test = test(column);
            if (test != status){
                getTable().setColumnHidden(ci, !test);
            }
        }
    }
    
    protected boolean test(Column column){
        if (c_columnFilters == null || c_columnFilters.size() == 0) return true;
        for (ColumnFilter filter : c_columnFilters){
            if (filter.acceptColumn(column)) return true;
        }
        return false;
    }
    
    /**
     *
     * @param filters
     */
    public void addRowFilter(RowFilter... filters){
        c_filteredDataSource.addRowFilter(filters);
    }
    
    public void clearRowFilters(){
        c_filteredDataSource.clearRowFilters();
    }

    @Override
    public void mouseClicked(MouseEvent me) {
        if(isQuickPlot() && me.getClickCount()==1 && me.getButton() == MouseEvent.BUTTON1){            
            int row = getTable().YtoRow(me.getY() + table.getVertSB().getValue());            
            if(isQuickPlotRow(row)){
                int column = getTable().XtoColumn(me.getX() + table.getHorizSB().getValue());
                Object value = getObject(row, column);
                if(value instanceof Boolean){
                    Boolean plot = (Boolean) value;
                    setTableDataItem(!plot, row, column);                    
                }                
            }
        }
    }

    @Override
    public void mousePressed(MouseEvent me) {
        
    }

    @Override
    public void mouseReleased(MouseEvent me) {
        
    }

    @Override
    public void mouseEntered(MouseEvent me) {
        
    }

    @Override
    public void mouseExited(MouseEvent me) {
        
    }
        
    
    class DataSourceWrapper implements EditableTableDataModel{
        private TableDataModel c_model;
        List<JCTableDataListener> listeners;
//        private WepsTableDataView c_view;
        /**
         *
         * @param model
         * @param view
         */
        public DataSourceWrapper(TableDataModel model, WepsTableDataView view){
            if (c_filteredDataSource == null){
                c_filteredDataSource = new FilteredDataSource(model);
            } else{
                c_filteredDataSource.setDataSource(model);
            }
            listeners = new ArrayList<JCTableDataListener>();
            c_model = c_filteredDataSource;
  //          c_view = view;
        }
        /**
         *
         * @return
         */
        public int getNumColumns(){
            return c_model.getNumColumns();
        }
        
        /**
         *
         * @return
         */
        public int getNumRows(){
            return c_model.getNumRows();
        }
        
        /**
         *
         * @param columnIndex
         * @return
         */
        public Object getTableColumnLabel(int columnIndex){
            return c_model.getTableColumnLabel(columnIndex);
        }
        
        /**
         *
         * @param rowIndex
         * @param columnIndex
         * @return
         */
        public Object getTableDataItem(int rowIndex, int columnIndex){
            rowIndex = rowIndex - getMeta().getLabelRowCount() + (isQuickPlot() ? 0 : 1);
            return c_model.getTableDataItem(rowIndex, columnIndex);
        }
        
        public boolean setTableDataItem(Object o, int rowIndex, int columnIndex) {
            if(isQuickPlotRow(rowIndex)){
                boolean plot = o instanceof Boolean ? (Boolean)o : false;
                getMeta().getColumn(columnIndex).setQuickPlot(plot);     
                JCTableDataEvent event = null;
                for(JCTableDataListener listener : listeners){
                    if(event == null){
                        event = new JCTableDataEvent(this, rowIndex, columnIndex, 1, 0, JCTableDataEvent.CHANGE_VALUE);                        
                    }
                    listener.dataChanged(event);
                }                
                return true;
            }
            rowIndex = rowIndex - (getMeta().getLabelRowCount() - 1);
            if (c_model instanceof EditableTableDataModel){
                return ((EditableTableDataModel)c_model).setTableDataItem(o, rowIndex, columnIndex);
            } else{
                return false;
            }
        }
        
        /**
         *
         * @param rowIndex
         * @return
         */
        public Object getTableRowLabel(int rowIndex){
            rowIndex = rowIndex - getMeta().getLabelRowCount() + 1;
            return c_model.getTableRowLabel(rowIndex);            
        }
        
        
        /**
         *
         * @param listener
         */
        public void addTableDataListener(JCTableDataListener listener){
            c_model.addTableDataListener(listener);
            listeners.add(listener);
        }
        
        /**
         *
         * @param listener
         */
        public void removeTableDataListener(JCTableDataListener listener){
            c_model.removeTableDataListener(listener);
            listeners.remove(listener);
        }
    }


    
    
    
}
