package railo.runtime.sql;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import railo.runtime.sql.exp.Column;
import railo.runtime.sql.exp.Expression;
import railo.runtime.sql.exp.op.Operation;
import railo.runtime.sql.exp.value.ValueNumber;

public class Selects {

	private List orderbys=new ArrayList();
	private List selects=new ArrayList();
	


	public void addOrderByExpression(Column exp) {
		this.orderbys.add(exp);
	}

	/**
	 * @return the orderbys
	 */
	public Column[] getOrderbys() {
		if(orderbys==null) return new Column[0];
		return (Column[]) orderbys.toArray(new Column[orderbys.size()]);
	}

	public void addSelect(Select select) {
		selects.add(select);
	}
	
	public Select[] getSelects() {
		if(selects==null) return new Select[0];
		return (Select[]) selects.toArray(new Select[selects.size()]);
	}
	

	@Override

	public String toString() {
		return _toString(this);
	}
	public static String _toString(Selects __selects) {
		Select[] _selects = __selects.getSelects();
		Select s;
		StringBuffer sb=new StringBuffer();
		
		for(int y=0;y<_selects.length;y++) {
			s = _selects[y];
			
			if(y>0) {
				if(s.isUnionDistinct())sb.append("union distinct\n\n");
				else sb.append("union\n\n");
			}
			
			sb.append("select\n\t");

			if(s.isDistinct()) sb.append("distinct\n\t");
			ValueNumber top = s.getTop();
			if(top!=null) sb.append("top "+top.getString()+"\n\t");
			// select
			Expression[] sels = s.getSelects();
			Expression exp;
			boolean first=true;
			for(int i=0;i<sels.length;i++) {
				if(!first)sb.append("\t,");
				exp=sels[i];
				sb.append(exp.toString(false)+"\n");
				first=false;
			}
	
			// from
			sb.append("from\n\t");
			Column[] forms = s.getFroms();
			first=true;
			for(int i=0;i<forms.length;i++) {
				if(!first)sb.append("\t,");
				exp=forms[i];
				sb.append(exp.toString(false)+"\n");
				first=false;
			}
	
			// where
			if(s.getWhere()!=null){
				sb.append("where \n\t");
				sb.append(s.getWhere().toString(true));
				sb.append("\n");
			}
	
			// group by
			Column[] gbs = s.getGroupbys();
			if(gbs.length>0) {
				sb.append("group by\n\t");
				first=true;
				for(int i=0;i<gbs.length;i++) {
					if(!first)sb.append("\t,");
					exp=gbs[i];
					sb.append(exp.toString(false)+"\n");
					first=false;
				}
			}
	
			
			// having
			Operation having = s.getHaving();
			if(having!=null){
				sb.append("having \n\t");
				sb.append(having.toString(true));
				sb.append("\n");
			}
			
		}

		// order by
		if(__selects.orderbys!=null && __selects.orderbys.size()>0) {
			sb.append("order by\n\t");
			Iterator it = __selects.orderbys.iterator();
			Expression exp;
			boolean first = true;
			while(it.hasNext()) {
				if(!first)sb.append("\t,");
				exp=(Expression) it.next();
				sb.append(exp.toString(false)+" "+(exp.isDirectionBackward()?"DESC":"ASC")+"\n");
				first=false;
			}
		}
		return sb.toString();
	}

	public Column[] getTables() {
		Iterator it = selects.iterator();
		Select s;
		ArrayList rtn=new ArrayList();
		Column[] froms;
		while(it.hasNext()) {
			s=(Select) it.next();
			froms = s.getFroms();
			for(int i=0;i<froms.length;i++) {
				rtn.add(froms[i]);
			}
		}
		return (Column[]) rtn.toArray(new Column[rtn.size()]);
	}

	public boolean isDistinct() {
		Select s;
		int len=selects.size();
		if(len==1) {
			s=(Select)selects.get(0);
			return s.isDistinct();
		}
		for(int i=1;i<len;i++) {
			s=(Select)selects.get(i);
			if(!s.isUnionDistinct()) return false;
		}
		return true;
	}
}

@@ -307,16 +307,24 @@
 ate List
+%3CColumn%3E
  orderby
@@ -334,24 +334,32 @@
 ew ArrayList
+%3CColumn%3E
 ();%0A%09private
@@ -363,16 +363,24 @@
 ate List
+%3CSelect%3E
  selects
@@ -389,24 +389,32 @@
 ew ArrayList
+%3CSelect%3E
 ();%0A%09%0A%0A%0A%09pub
@@ -606,27 +606,16 @@
 %09%09return
- (Column%5B%5D)
  orderby
@@ -800,24 +800,24 @@
 ect%5B0%5D;%0A
+
 %09%09return
  (Select
@@ -812,19 +812,8 @@
 turn
- (Select%5B%5D)
  sel
@@ -2622,24 +2622,32 @@
 %0A%09%09%09Iterator
+%3CColumn%3E
  it = __sele
@@ -2784,21 +2784,8 @@
 exp=
-(Expression) 
 it.n
@@ -2972,16 +2972,24 @@
 Iterator
+%3CSelect%3E
  it = se
@@ -3029,16 +3029,24 @@
 rrayList
+%3CColumn%3E
  rtn=new
@@ -3055,16 +3055,24 @@
 rrayList
+%3CColumn%3E
 ();%0A%09%09Co
@@ -3118,17 +3118,8 @@
 %09%09s=
-(Select) 
 it.n
@@ -3231,19 +3231,8 @@
 turn
- (Column%5B%5D)
  rtn
@@ -3354,32 +3354,24 @@
 ==1) %7B%0A%09%09%09s=
-(Select)
 selects.get(
@@ -3440,16 +3440,8 @@
 %09%09s=
-(Select)
 sele

add generic types