package com.pictc.jdbc;

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

import com.pictc.jdbc.model.Criteria;
import com.pictc.jdbc.model.CriteriaGroup;
import com.pictc.jdbc.model.JdbcParam;
import com.pictc.jdbc.model.JdbcType;
import com.pictc.jdbc.model.Link;
import com.pictc.jdbc.model.QueryOrder;
import com.pictc.jdbc.model.Criteria.DataType;
import com.pictc.jdbc.model.QueryOrder.QueryOrderType;
import com.pictc.utils.StringUtils;

public class QueryParameterUtils {
	
	private static final String TBL_ALIAS = "t";
	
	public static List<JdbcParam> toJdbcParams(SqlBuilder sql,List<CriteriaGroup> groups) {
		List<JdbcParam> params = new ArrayList<JdbcParam>();
		boolean hasWhere = false;
		if(groups!=null && !groups.isEmpty()) {
			for (CriteriaGroup group : groups) {
				List<Criteria> cris = group.getCriterias();
				if(cris==null || cris.isEmpty()) {
					continue;
				}
				if(!hasWhere) {
					hasWhere = true;
					sql.where();
				}else {
					if(group.getLink()==Link.AND) {
						sql.and();
					}else {
						sql.or();
					}
				}
				sql.leftBracket();
				boolean c_flag = false;
				for (Criteria criteria : cris) {
					if(!c_flag) {
						c_flag = true;
					}else {
						if(criteria.getLink()==Link.AND) {
							sql.and();
						}else {
							sql.or();
						}
					}
					
					if(criteria.isNot()) {
						sql.not();
					}
					String col = convertHump(criteria.getField());
					if(criteria.getDataType()==DataType.STRING) {
						sql.append("IFNULL(");
						sql.append(TBL_ALIAS).dot().appendSeparator(col);
						sql.append(",'')");
					}else {
						sql.append(TBL_ALIAS).dot().appendSeparator(col);
					}
					JdbcType jdbc = criteria.getJdbc();
					int valueType = 0;
					switch (criteria.getType()) {
						case NULL:
							valueType = -1;
							sql.isNull();
							break;
						case EQ:
							sql.eq().placeholder();
							break;
						case LIKE:
							sql.like().placeholder();
							break;
						case GT:
							sql.gt().placeholder();
							break;
						case EQ_GT:
							sql.gtEq().placeholder();
							break;
						case LT:
							sql.lt().placeholder();
							break;
						case EQ_LT:
							sql.ltEq().placeholder();
							break;
						case BETWEEN:
							valueType = 1;
							if(criteria.getVal()==null || criteria.getSecondVal()==null) {
								throw new RuntimeException(StringUtils.format("filed:[{0}] --> 条件：BETWEEN 值不能为空！", criteria.getField()));
							}
							sql.between().placeholder().and().placeholder();
							params.add(new JdbcParam().setJdbc(jdbc.getJdbc()).setJavaType(jdbc.getJavaClass()).setVal(criteria.getVal()));
							params.add(new JdbcParam().setJdbc(jdbc.getJdbc()).setJavaType(jdbc.getJavaClass()).setVal(criteria.getSecondVal()));
							break;
						case IN:
							valueType = 2;
							//criteria.getListVal()
							if(criteria.getListVal()==null || criteria.getListVal().isEmpty()) {
								throw new RuntimeException(StringUtils.format("filed:[{0}] --> 条件：IN 值不能为空！", criteria.getField()));
							}
							sql.inStart();
							boolean inFlag = false;
							for (Object val : criteria.getListVal()) {
								if(!inFlag) {
									inFlag = true;
								}else {
									sql.comma();
								}
								sql.placeholder();
								params.add(new JdbcParam().setJdbc(jdbc.getJdbc()).setJavaType(jdbc.getJavaClass()).setVal(val));
							}
							sql.inEnd();
							break;
						default:
							break;
					}
					
					if(valueType==0) {
						params.add(new JdbcParam().setJdbc(jdbc.getJdbc()).setJavaType(jdbc.getJavaClass()).setVal(criteria.getVal()));
					}
				}
				sql.rightBracket();
			}
		}
		return params;
	}
	
	
	public static void parseOrders(SqlBuilder builder,List<QueryOrder> orders) {
		if(orders!=null) {
			boolean flag = false;
			for (QueryOrder order : orders) {
				if(order.getType()==QueryOrderType.NONE) {
					continue;
				}
				if(!flag) {
					builder.orderBy();
					flag = true;
				}else {
					builder.comma();
				}
				String col = convertHump(order.getField());
				builder.space().append(TBL_ALIAS).dot().appendSeparator(col);
				if(order.getType()==QueryOrderType.ASC) {
					builder.asc();
				}else {
					builder.desc();
				}
			}
		}
	}
	
	/**
	 * 将驼峰命名的字符串转为下划线
	 * */
	public static String convertHump(String str) {
		StringBuilder result=new StringBuilder();
		char[] chars=str.toCharArray();
		for (int i = 0; i < chars.length; i++) {
			if(Character.isUpperCase(chars[i])) {
				if(i>0) {
					result.append('_');
				}
				result.append(Character.toLowerCase(chars[i]));
				continue;
			}
			result.append(chars[i]);
		}
		return result.toString();
	}
	

}
