package cn.orm.util.builder.base;

import java.util.StringJoiner;

import cn.util.core.IsKit;

public class SQLQuery {
	
	protected StringBuilder builder = null;
	protected StringJoiner orderJoiner = null;// ordering
	
	/***
	 * Constructor
	 */
	public SQLQuery() {
		builder = new StringBuilder().append(' ');
	}
	
	/* Select */
	public SQLQuery selectD(String target) {
		builder.append("SELECT Distinct ").append(target).append(' ').toString();
		return this;
	}
	/***
	 * What to query
	 * @param target		Selection target from table
	 * @return				query
	 */
	public SQLQuery select(String target) {
		builder.append("SELECT ").append(target).append(' ').toString();
		return this;
	}
	
	/***
	 * What to query
	 * @param target		Selection targets from table
	 * @return				query
	 */
	public SQLQuery select(String... targets) {
		builder.append("SELECT ");
		StringJoiner joiner = new StringJoiner(", ");
		for (String str : targets)
			joiner.add(str);
		builder.append(joiner.toString()).append(' ');
		return this;
	}
	
	/***
	 * What to query
	 * @param target		Selection target from table
	 * @return				query
	 */
	public SQLQuery select(char target) {
		return select(Character.toString(target));
	}
	
	public SQLQuery fromSubquery(String subquery) {
		builder.append("FROM (").append(subquery).append(") ");
		return this;
	}
	
	/***
	 * Where to query
	 * @param tableName		Selection destination
	 * @return				query
	 */
	public SQLQuery from(String tableName) {
		builder.append("FROM ").append(tableName).append(' ');
		return this;
	}
	
	/***
	 * Where to query
	 * @param subquery		Selection destination (subquery)
	 * @return				query
	 */
	public SQLQuery joinWhere(String subquery) {
		builder.append(subquery);
		return this;
	}
	
	/***
	 * Where to query
	 * @param subquery		Selection destination (subquery)
	 * @return				query
	 */
	public SQLQuery fromSubquery(SQLSubquery subquery) {
		builder.append("FROM (").append(subquery.create()).append(") ");
		return this;
	}
	
	/***
	 * How to query
	 * @param condition		Selection condition (manual or from Attribute)
	 * @return				query
	 */
	public SQLQuery where(String condition) {
		builder.append("WHERE ").append(condition).append(' ');
		return this;
	}
	
	/***
	 * How to query
	 * @param condition		Selection condition (manual or from Attribute)
	 * @return				query
	 */
	public SQLQuery where(SQLCondition condition) {
		if (IsKit.isNotNullOrEmpty(condition)) {
			builder.append("WHERE ").append(condition.create()).append(' ');
		}
		return this;
	}
	
	/***
	 * How to order ASC
	 * @param attributeName	Selection ordering
	 * @param ascending		order direction
	 * @return				query
	 */
	public SQLQuery orderBy(String attributeName, boolean ascending) {
		if (orderJoiner == null)
			orderJoiner = new StringJoiner(", ");
		orderJoiner.add(attributeName + (ascending ? "" : " DESC"));
		return this;
	}
	
	/***
	 * How to order
	 * @param attributeName	Selection ordering
	 * @param ascending		order direction
	 * @return				query
	 */
	public SQLQuery orderBy(char attributeName, boolean ascending) {
		if (orderJoiner == null)
			orderJoiner = new StringJoiner(", ");
		orderJoiner.add(attributeName + (ascending ? "" : " DESC"));;
		return this;
	}
	
	/***
	 * How to group
	 * @param attributeName	Selection grouping
	 * @return				query
	 */
	public SQLQuery groupBy(char attributeName) {
		builder.append("GROUP BY ").append(attributeName).append(' ');
		return this;
	}
	
	/***
	 * How to group
	 * @param attributeName	Selection grouping
	 * @return				query
	 */
	public SQLQuery groupBy(String attributeName) {
		builder.append("GROUP BY ").append(attributeName).append(' ');
		return this;
	}
	
	/***
	 * Reset query
	 * @return				query
	 */
	public SQLQuery limit(String range) {
		builder.append(" Limit ").append(range).append(' ');
		return this;
	}
	/***
	 * Reset query
	 * @return				query
	 */
	public SQLQuery clear() {
		builder = new StringBuilder().append(' ');
		return this;
	}
	
	/***
	 * Return the final query
	 * @return 				query string
	 */
	public String create() {
		return toString();
	}
	
	/***
	 * Return the final query
	 */
	@Override
	public String toString() {
		return builder.append(orderJoiner != null ? "ORDER BY " : "").append(orderJoiner != null ? orderJoiner.toString() : "").toString().trim();
	}
}

