package de.brightbyte.db;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Iterator;

import de.brightbyte.data.cursor.ColumnDataCursor;
import de.brightbyte.data.cursor.ColumnDataSet;
import de.brightbyte.data.cursor.CursorIterator;
import de.brightbyte.data.cursor.DataRow;
import de.brightbyte.util.PersistenceException;
import de.brightbyte.util.UncheckedPersistenceException;


public class DatabaseColumnDataSet implements ColumnDataSet {
	
	protected String[] columns;
	
	protected class ResultSetCursor implements ColumnDataCursor {

		protected ResultSet resultSet;
		protected ResultSetRow row;

		protected class ResultSetRow implements DataRow {

			public String[] getColumnNames() {
				return columns;
			}

			public byte getByte(String column) throws PersistenceException {
				try {
					return resultSet.getByte(column);
				} catch (SQLException e) {
					throw new PersistenceException(e);
				}
			}

			public double getDouble(String column) throws PersistenceException {
				try {
					return resultSet.getDouble(column);
				} catch (SQLException e) {
					throw new PersistenceException(e);
				}
			}

			public float getFloat(String column) throws PersistenceException {
				try {
					return resultSet.getFloat(column);
				} catch (SQLException e) {
					throw new PersistenceException(e);
				}
			}

			public int getInt(String column) throws PersistenceException {
				try {
					return resultSet.getInt(column);
				} catch (SQLException e) {
					throw new PersistenceException(e);
				}
			}

			public long getLong(String column) throws PersistenceException {
				try {
					return resultSet.getLong(column);
				} catch (SQLException e) {
					throw new PersistenceException(e);
				}
			}

			public Object getObject(String column) throws PersistenceException {
				try {
					return resultSet.getObject(column);
				} catch (SQLException e) {
					throw new PersistenceException(e);
				}
			}

			public short getShort(String column) throws PersistenceException {
				try {
					return resultSet.getShort(column);
				} catch (SQLException e) {
					throw new PersistenceException(e);
				}
			}
		}
		
		public ResultSetCursor(ResultSet resultSet) {
			this.resultSet = resultSet;
		}
		

		public String[] getColumnNames() {
			return columns;
		}

		protected void finalize() {
			close();
		}

		public void close() {
			try {
				resultSet.close();
			} catch (SQLException e) {
				//ignore. who cares?
			}
		}

		public DataRow next() throws PersistenceException {
			try {
				if (!resultSet.next()) return null;
				else return row;
			} catch (SQLException e) {
				throw new PersistenceException(e);
			}
		}
	}
	
	protected DatabaseAccess access;
	protected String name;
	protected String sql;
	
	public DatabaseColumnDataSet(DatabaseAccess access, String name, String sql) {
		super();
		this.access = access;
		this.name = name;
		this.sql = sql;
	}
	
	public Iterator<DataRow> iterator() throws UncheckedPersistenceException  {
		try {
			return new CursorIterator<DataRow>(cursor());
		} catch (PersistenceException e) {
			throw new UncheckedPersistenceException(e); //XXX: fugly hack :(
		}
	}

	public ColumnDataCursor cursor() throws PersistenceException  {
		try {
			String sql = getSQL();
			ResultSet rs = access.executeQuery(name, sql);
			return new ResultSetCursor(rs);
		} catch (SQLException e) {
			throw new PersistenceException(e); 
		}
	}

	protected String getSQL() {
		if (sql==null) throw new IllegalStateException("No SQL query known. either provide an sql query to the constructor, or override getSQL()!");
		return sql;
	}
	
}
