package de.muntjak.tinylookandfeel.controlpanel;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Vector;

import javax.swing.Icon;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

import de.muntjak.tinylookandfeel.controlpanel.NonSortableTableModel.Record;
import de.muntjak.tinylookandfeel.table.SortableTableData;


/**
 * An example table model implementing SortableTableData.
 * See de.muntjak.tinylookandfeel.controlpanel.NonSortableTableModel
 * for details about the data structure.
 * 
 * @author Hans Bickel
 *
 */
public class TinyTableModel extends NonSortableTableModel implements SortableTableData {

	public TinyTableModel() {
		super(true);
	}
	
// SortableTableData implementation
	
	public boolean isColumnSortable(int column) {
		// Note: For TinyTableModel this works fine. You may
		// take another approach depending on your kind of data.
		if(data.isEmpty()) return false;
		
		// value at column #1 is of type Icon (which doesn't implement Comparable)
		return (getValueAt(0, column) instanceof Comparable);
	}
	
	public boolean supportsMultiColumnSort() {
		// We support multi column sort
		return true;
	}

	public void sortColumns(final int[] columns, final int[] sortingDirections, JTable table) {
		// Prerequisites for restoring the selection
		int[] sr = table.getSelectedRows();
		int[] sc = table.getSelectedColumns();
		int rowIndex = 0;
		
		Iterator ii = data.iterator();
		while(ii.hasNext()) {
			((Record)ii.next()).setOldRow(rowIndex ++);
		}

		// The sorting part...
		if(columns.length == 0) {
			// The natural order of our data depends on first (Integer) column
			Collections.sort(data, new Comparator() {
				public int compare(Object o1, Object o2) {
					// For our data we know that arguments are
					// non-null and are of type Record.
					Record r1 = (Record)o1;
					Record r2 = (Record)o2;
					Comparable val1 = (Comparable)r1.getValueAt(0);
					Comparable val2 = (Comparable)r2.getValueAt(0);
					
					return val1.compareTo(val2);
				}
			});
		}
		else {
			// Multi column sort
			Collections.sort(data, new Comparator() {
				public int compare(Object o1, Object o2) {
					// For our data we know that arguments are
					// non-null and are of type Record.
					Record r1 = (Record)o1;
					Record r2 = (Record)o2;
					
					for(int i = 0; i < columns.length; i++) {
						Comparable val1 = (Comparable)r1.getValueAt(columns[i]);
						Comparable val2 = (Comparable)r2.getValueAt(columns[i]);
						int result = val1.compareTo(val2);
						
						if(result != 0) {
							if(sortingDirections[i] == SORT_DESCENDING) {
								return -result;
							}
							
							return result;
						}
					}
					
					return 0;
				}
			});
		}

		// Tell our listeners that data has changed
		fireTableDataChanged();
		
		// Restore selection
		rowIndex = 0;
		
		ii = data.iterator();
		while(ii.hasNext()) {
			((Record)ii.next()).setNewRow(rowIndex ++);
		}
		
		Vector temp = (Vector)data.clone();
		Collections.sort(temp, new Comparator() {
			public int compare(Object o1, Object o2) {
				Record r1 = (Record)o1;
				Record r2 = (Record)o2;
				
				if(r1.getOldRow() > r2.getOldRow()) return 1;
				
				return -1;
			}
		});

		// Adding one row selection interval after another is
		// probably inefficient.
		for(int i = 0; i < sr.length; i++) {
			int row = ((Record)temp.get(sr[i])).getNewRow();
			table.addRowSelectionInterval(row, row);
		}

		for(int i = 0; i < sc.length; i++) {
			table.addColumnSelectionInterval(sc[i], sc[i]);
		}
	}
}
