package com.quantum.view.tableview;

import java.sql.SQLException;
import java.util.Vector;

import com.quantum.Messages;
import com.quantum.adapters.AdapterFactory;
import com.quantum.adapters.DatabaseAdapter;
import com.quantum.model.Bookmark;
import com.quantum.model.Entity;
import com.quantum.model.NotConnectedException;
import com.quantum.sql.FilterSort;
import com.quantum.sql.SQLHelper;
import com.quantum.sql.SQLResults;

import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;

public class TableAdapter {
	
	private Table table = null;
	
	public static final String DEFAULT = ""; //$NON-NLS-1$
	public static final String UTF_8 = "UTF-8"; //$NON-NLS-1$
	public static final String UTF_16 = "UTF-16"; //$NON-NLS-1$
	
	private int pageSize = DefaultSizes.PAGE_SIZE;
	private int maxColumnSize = DefaultSizes.MAX_COLUMN_SIZE;
	private FilterSort extra = new FilterSort();
	private int offset = 1;
	private int totalSize = -1;
	private Vector rows = new Vector();
	private Vector columnNames = new Vector();
	private boolean hasMore = false;
	
	private Bookmark bookmark = null;	
    private Entity entity = null;
	private String query;
	
	private String encoding = ""; //$NON-NLS-1$
	
    private TableAdapter(Entity entity) {
        this.entity = entity;
        this.bookmark = entity.getBookmark();
    }
	private TableAdapter(Bookmark bookmark) {
		this.bookmark = bookmark;
	}
	public void fullMode() {
		offset = 1;
		pageSize = Integer.MAX_VALUE;
	}
	public void resetMode() {
		offset = 1;
		pageSize = DefaultSizes.PAGE_SIZE;
	}
	public static TableAdapter createFromQuery(Bookmark bookmark, SQLResults results) throws NotConnectedException {
		TableAdapter retVal = new TableAdapter(bookmark);
		retVal.setQuery(results.getQuery());
		retVal.setData(results);
		return retVal;
	}
	public static TableAdapter createFromTable(Entity entity) {
		TableAdapter retVal = new TableAdapter(entity); 
		return retVal;
	}
	private void loadSize() {
        try {
    		if (entity != null) {
                totalSize = SQLHelper.getSize(
                    bookmark.getConnection(), entity.getCondQualifiedName(), 
                        AdapterFactory.getInstance().getAdapter(bookmark.getType()));
    		}
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (NotConnectedException e) {
            e.printStackTrace();
        }
	}
	public int getStartIndex() {
		if (totalSize == 0) {
			return 0;
		}
		return offset;
	}
	public int getEndIndex() {
		return offset + rows.size() - 1;
	}
	public int getTotalSize() {
		return totalSize;
	}
	public void nextPage() {
		loadSize();
		offset = offset + pageSize;
		if (totalSize >= 0 && offset > totalSize) {
			offset = offset - pageSize;
		}
	}
	public void previousPage() {
		offset = offset - pageSize;
		if (offset < 1) {
			offset = 1;
		}
	}
	public boolean hasNextPage() {
		if (entity != null) {
			if (offset + pageSize <= totalSize) {
				return true;
			}
			return false;
		}
		return hasMore;
	}
	public boolean hasPreviousPage() {
		if (offset > 1) {
			return true;
		}
		return false;
	}

	public String getQuery() {
		if (entity != null) {
			DatabaseAdapter adapter = AdapterFactory.getInstance().getAdapter(bookmark.getType());
			if (adapter == null) throw new RuntimeException();
			else return adapter.getTableQuery((entity).getCondQualifiedName()) + extra.toString();
		}
		return query;
	}
	public void loadData() throws NotConnectedException {
		loadSize();
		if (entity != null) {
			if (offset > totalSize) {
				offset = 1;
			}
		}
		String query = getQuery();
		System.out.println(offset + Messages.getString("TableAdapter.to") + (offset + pageSize - 1)); //$NON-NLS-1$
		SQLResults results = SQLHelper.getResults(bookmark.getConnection(), query, offset, offset + pageSize - 1, maxColumnSize, encoding);
		setData(results);
	}
	public void resetOffset() {
		offset = 1;
	}
	public void setData(SQLResults results) throws NotConnectedException {
        if (results.isError()) return;
		int rowCount = results.getRowCount();
		int columnCount = results.getColumnCount();
		rows = new Vector();
		columnNames = new Vector();
		for (int col = 1; col <= columnCount; col++) {
			columnNames.addElement(results.getColumnName(col));
		}
		for (int row = 1; row <= rowCount; row++) {
			String rowData[] = new String[columnCount];
			for (int col = 1; col <= columnCount; col++) {
				rowData[col - 1] = results.getElement(col, row).toString();
			}
			rows.addElement(rowData);
		}
		hasMore = results.hasMore();
		if (entity == null && results.getMaxSize() >= 0) {
			if (offset > results.getMaxSize()) {
				offset = 1;
				loadData();
			}
		}
	}
	public void loadTable(Table table) {
		this.table = table;
		table.setHeaderVisible(true);
		for (int i = 0; i < columnNames.size(); i++) {
			TableColumn column = new TableColumn(table, SWT.NONE);
			column.setText(columnNames.elementAt(i).toString());
		}
		for (int i = 0; i < columnNames.size(); i++) {
			table.getColumn(i).pack();
		}
		for (int row = 0; row < rows.size(); row++) {
			TableItem item = new TableItem(table, SWT.NONE);
			String itemData[] = (String[]) rows.elementAt(row);
			item.setText(itemData);
		}
		for (int i = 0; i < columnNames.size(); i++) {
			table.getColumn(i).pack();
		}
	}
	
	public TableViewer addTableViewer(Table table) {
		TableViewer tableViewer = new TableViewer(table);
		tableViewer.setUseHashlookup(true);
		String[] colNams = new String[columnNames.size()];
		for (int i = 0; i < columnNames.size(); i++) {
			colNams[i] = (String) columnNames.get(i);
		}
		tableViewer.setColumnProperties(colNams);

		// Create the cell editors
		CellEditor[] editors = new CellEditor[columnNames.size()];
		for (int i = 0; i < columnNames.size(); i++) {
			TextCellEditor textEditor = new TextCellEditor(table);
			((Text) textEditor.getControl()).setTextLimit(60);
			editors[i] = textEditor;
		}
		// Assign the cell editors to the viewer 
		tableViewer.setCellEditors(editors);
		// Set the cell modifier for the viewer
		//tableViewer.setCellModifier(new MetaDataModifier(this));
		// Set the default sorter for the viewer 
		//tableViewer.setSorter(new ExampleTaskSorter(ExampleTaskSorter.DESCRIPTION));
		
		return tableViewer;
	}
	
	public int getPageSize() {
		return pageSize;
	}
	
	public void setFilterSort(FilterSort extra) {
		this.extra = extra;
	}
	public String getTable() {
		return (entity != null) ? entity.getCondQualifiedName() : null;
	}

	public void setQuery(String query) {
		this.query = query;
	}
	public String getEncoding() {
		return encoding;
	}

	public void setEncoding(String encoding) {
		this.encoding = encoding;
	}
	public String getStatusString() {
		String status = getStartIndex() + Messages.getString("TableAdapter.to") + getEndIndex() + Messages.getString("TableAdapter.of") + //$NON-NLS-1$ //$NON-NLS-2$
				getTotalSize();
		if (!encoding.equals(DEFAULT)) {
			status += " (" + encoding + ")"; //$NON-NLS-1$ //$NON-NLS-2$
		}
		String filterText = extra.toString();
		if (!filterText.equals("")) { //$NON-NLS-1$
			status += " (" + filterText + ")"; //$NON-NLS-1$ //$NON-NLS-2$
		}
		if (pageSize == Integer.MAX_VALUE) {
			status += Messages.getString("TableAdapter.full"); //$NON-NLS-1$
		}
		return status;
	}
	/**
	 * @return
	 */
	public Bookmark getBookmark() {
		return this.bookmark;
	}
    /**
     * @return
     */
    public Entity getEntity() {
        return entity;
    }

}