package com.approximatrix.draco.application.plugin.ui;

import java.util.ArrayList;
import java.util.List;

import javax.swing.event.EventListenerList;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

import com.approximatrix.draco.application.plugin.VariableSelectionColumn;
import com.approximatrix.draco.datamodel.StatTableModel;

public class SelectionTableModel implements TableModel {

	private static final String VARIABLE_NAME_COLUMN = "Variable";
	
	private StatTableModel statModel = null;
	private List<VariableSelectionColumn> cols = null;
	
	/** The listener list. */
    protected EventListenerList listener = null;
	
	public SelectionTableModel(List<VariableSelectionColumn> columns, StatTableModel model) {
		cols = columns;
		if(cols == null)
			cols = new ArrayList<VariableSelectionColumn>(0);
		statModel = model;
		
		listener = new EventListenerList();
	}
	
	public void addTableModelListener(TableModelListener l) {
		listener.add(TableModelListener.class,l);
	}

	public Class<?> getColumnClass(int columnIndex) {
		if(columnIndex == 0)
			return String.class;
		else
			return Boolean.class;
	}

	public int getColumnCount() {
		return cols.size()+1;
	}

	public String getColumnName(int columnIndex) {
		if(columnIndex == 0)
			return VARIABLE_NAME_COLUMN;
		else
			return cols.get(columnIndex-1).getTitle();
	}

	public int getRowCount() {
		return statModel.getColumnCount();
	}

	public Object getValueAt(int rowIndex, int columnIndex) {
		try {
			String varName = statModel.getVariable(rowIndex).getName();
			if(columnIndex == 0)
				return varName;
			VariableSelectionColumn col = cols.get(columnIndex-1);
			return new Boolean(col.isSelected(varName));
		} catch(Exception e) {
			return null;
		}
	}

	public boolean isCellEditable(int rowIndex, int columnIndex) {
		if(columnIndex == 0)
			return false;
		else
			return true;
	}

	public void removeTableModelListener(TableModelListener l) {
		listener.remove(TableModelListener.class, l);
	}

	public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
		if(columnIndex == 0) return;
		if(aValue instanceof Boolean) {
			String varName = statModel.getVariable(rowIndex).getName();
			if(((Boolean)aValue).booleanValue()) {
				cols.get(columnIndex-1).setSelected(varName);
				checkExclusivity(columnIndex,varName);
			} else
				cols.get(columnIndex-1).setUnselected(varName);
		}
		this.fireTableModelChanged();
	}

	private void checkExclusivity(int columnIndex, String varName) {
		VariableSelectionColumn justClicked = cols.get(columnIndex-1);
		for(VariableSelectionColumn col : cols) {
			if(justClicked == col) continue;
			
			if(justClicked.isExclusive() || col.isExclusive()) {
				col.setUnselected(varName);
			}
		}
	}
	
	public void fireTableModelChanged() {
		TableModelEvent e = new TableModelEvent(this);
		Object[] ls = listener.getListenerList();
		for (int i = (ls.length - 2); i >= 0; i-=2) {
			if (ls[i] == TableModelListener.class) {
				((TableModelListener)ls[i + 1]).tableChanged(e);
			}
		}
	}
	
}
