package org.seamframework.sql;

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

public class From<X> {
	
	private List<Join<?>> joins = new ArrayList<Join<?>>();

	private final class ColumnRef<Y> implements Expression<Y> {
		private final Column<X, Y> column;

		private ColumnRef(Column<X, Y> column) {
			this.column = column;
		}

		@Override
		public Type<Y> getType() {
			return column.getType();
		}

		@Override
		public String toSql() {
			return alias==null ? 
					column.getName() : 
					alias + '.' + column.getName();
		}
		@Override @SuppressWarnings("unchecked")
		public List<Parameter<?>> getParameters() {
			return Collections.EMPTY_LIST;
		}
	}

	private final Table<X> table;
	private final String alias;
	
	From(Table<X> table, String alias) {
		this.table = table;
		this.alias = alias;
	}
	
	From(Table<X> table) {
		this(table, null);
	}
	
	public <Y> Join<Y> join(Table<Y> table) {
		Join<Y> join = new Join<Y>(table);
		joins.add(join);
		return join;
	}
	
	public <Y> Join<Y> join(Table<Y> table, String alias) {
		Join<Y> join = new Join<Y>(table, alias);
		joins.add(join);
		return join;
	}
	
	public <Y> Expression<Y> get(final Column<X, Y> column) {
		return new ColumnRef<Y>(column);
	}
	
	public String toSql() {
		StringBuffer sql = new StringBuffer();
		if ( alias==null ) {
			sql.append( table.getQualifiedName() );
		}
		else {
			sql.append( table.getQualifiedName() )
				.append(" as ")
				.append(alias);
		}
		for (Join<?> join: joins) {
			sql.append( join.toSql() );
		}
		return sql.toString();
	}
		
}
