package lu.tudor.santec.gecamed.formeditor.gui.component;

import java.util.Vector;

import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.TableColumn;

import lu.tudor.santec.gecamed.formeditor.gui.model.ComboBoxElement;


public class EditableDataTableModel extends AbstractTableModel {
	
	private static final long serialVersionUID = 1L;
	
	private Vector<Vector<String>> data;
	
	private Vector<ComboBoxElement<String>> columnRefs;
	
	private DefaultTableColumnModel columnModel;
	
	
	
	public EditableDataTableModel () {
		data = new Vector<Vector<String>>();
		columnRefs = new Vector<ComboBoxElement<String>>();
		columnModel = new DefaultTableColumnModel();
	}
	

//	@Override
	public int getColumnCount() {
		return columnRefs.size();
	}

//	@Override
	public int getRowCount() {
		return data.size();
	}
	
//	@Override
    public Object getValueAt(int rowIndex, int columnIndex) {
		/* ======================================== */
		String value = "";
		
		if (rowIndex < data.size()) {
			Vector<String> rowData = data.get(rowIndex);
			
			if (columnIndex < rowData.size()) {
				value = rowData.get(columnIndex);
			}
		}
		
		return value;
		/* ======================================== */
	}
	
	@Override
	public void setValueAt (Object value, int rowIndex, int columnIndex) {
		/* ======================================== */
		while (rowIndex >= data.size()) {
			this.data.add(new Vector<String>());
		}
		
		Vector<String> rowData = data.get(rowIndex);
			
		while (columnIndex >= rowData.size()) {
			rowData.add("");
		}
		
		rowData.set(columnIndex, String.valueOf(value));
		
		fireTableCellUpdated(rowIndex, columnIndex);
		/* ======================================== */
	}
	
	@Override
    public String getColumnName(int columnIndex) {
		return columnRefs.get(columnIndex).getValue();
	}
	
	
	@Override
    public Class<?> getColumnClass(int columnIndex) {
    	return String.class;
    }
	
	@Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
    	return false;
    }
	
	public DefaultTableColumnModel getColumnModel () {
		return columnModel;
	}
	
	public int getColumnWidth (int index) {
		return columnModel.getColumn(index).getPreferredWidth();
	}
	
	public void setColumnWidth (int index, int width) {
		/* ======================================== */
		if (index < columnModel.getColumnCount()) {
			TableColumn col = columnModel.getColumn(index);
			col.setWidth(width);
			col.setPreferredWidth(width);
		}
		/* ======================================== */
	}
	
	public TableColumn getColumn (int index) {
		return columnModel.getColumn(index);
	}
	
	public void addRow (Vector<String> rowData) {
		/* ======================================== */
		this.data.add(rowData);
		
		fireTableRowsInserted(this.getRowCount(), this.getRowCount());
		/* ======================================== */
	}
	
	public void setData (Vector<Vector<String>> data, Vector<ComboBoxElement<String>> columnReferences) {
		/* ======================================== */
		this.data = data;
		this.columnRefs = columnReferences;
		
		fireTableDataChanged();
		/* ======================================== */
	}
	
	public Vector<Vector<String>> getData () {
		return this.data;
	}
	
	public Vector<ComboBoxElement<String>> getColumnReferences () {
		return this.columnRefs;
	}
	
	public Vector<String> getColumnNames () {
		/* ======================================== */
		Vector<String> columnNames = new Vector<String>();
		
		for (ComboBoxElement<String> cbe : this.columnRefs) {
			columnNames.add(cbe.getValue());
		}
		
		return columnNames;
		/* ======================================== */
	}
	
	public ComboBoxElement<String> getColumnReference(int index) {
		return columnRefs.get(index);
	}
	
	public void setColumnReference (ComboBoxElement<String> reference, int index) {
		columnRefs.set(index, reference);
		fireTableStructureChanged();
	}
	
	public void setColumnName (String name, int index) {
		columnRefs.get(index).setValue(name, index);
		fireTableStructureChanged();
	}
	

	public void addColumn (ComboBoxElement<String> columnValue) {
		addColumn(getColumnCount(), null, columnValue);
	}

	public void addColumn (int colIndex, ComboBoxElement<String> columnValue) {
		addColumn(colIndex, null, columnValue);
	}
	
	public void addColumn (Vector<String> columnData, ComboBoxElement<String> columnValue) {
		addColumn(getColumnCount(), columnData, columnValue);
	}
	
	public void addColumn (int colIndex, Vector<String> columnData, 
			ComboBoxElement<String> columnValue) {
		/* ======================================== */
		// add the reference
		columnRefs.add(colIndex, columnValue);
		
		// add the values in the columns
		for (int rowIndex = 0; rowIndex < getRowCount(); rowIndex++) {
			String value = "";
			if (columnData != null && rowIndex < columnData.size()) {
				value = columnData.get(rowIndex);
			}
			
			data.get(rowIndex).add(colIndex, value);
		}
		
		fireTableStructureChanged();
		/* ======================================== */
	}
	
	public void removeColumn (int index) {
		/* ======================================== */
		columnRefs.removeElementAt(index);
		
		for (Vector<String> rowData : data) {
			if (index < rowData.size()) {
				rowData.remove(index);
			}
		}
		/* ======================================== */
	}
	
	public void switchColumns (int index1, int index2) {
		/* ======================================== */
		// switch the columnNames
		ComboBoxElement<String> tmp = columnRefs.elementAt(index1);
		columnRefs.set(index1, columnRefs.elementAt(index2));
		columnRefs.set(index2, tmp);
		
		// switch the values
		for (Vector<String> rowData : data) {
			/* ---------------------------------------- */
			String s = rowData.get(index1);
			rowData.set(index1, rowData.get(index2));
			rowData.set(index2, s);
			/* ---------------------------------------- */
		}
		/* ======================================== */
	}
	
	public void fireTableStructureChanged () {
		// TODO:
		int[] width = new int[columnModel.getColumnCount()];
		for (int index = 0; index < columnModel.getColumnCount(); index++) {
			width[index] = this.getColumnWidth(index);
		}
		super.fireTableStructureChanged();
		for (int index = 0; index < width.length; index++) {
			this.setColumnWidth(index, width[index]);
		}
	}
}
