package cn.hmsoft.jdbc.generator;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.util.StringUtils;

import cn.hmsoft.exception.develop.PrimaryKeyNotDefinedException;
import cn.hmsoft.jdbc.entity.QueryOrder;
import cn.hmsoft.jdbc.entity.Table;
import cn.hmsoft.jdbc.entity.ValueCompareType;
import cn.hmsoft.jdbc.exception.JdbcException;
import cn.hmsoft.jdbc.exception.UpdateFullTableException;

public abstract class AbstractSQLGenerator implements ISQLGenerator {

	@Override
	public String count(Class<?> clazz) {
		return "select count(1) from " + TableHelper.getTable(clazz).tableName();
	}

	@Override
	public String count(Class<?> clazz, String columnName) {
		return "select count(1) from " + TableHelper.getTable(clazz).tableName() + " where " + columnName + "=?";
	}

	@Override
	public String count(Class<?> clazz, String columnName, ValueCompareType compareType) {
		return "select count(1) from " + TableHelper.getTable(clazz).tableName() + " where " + columnName + " "
				+ compareType.toString() + " ?";
	}

	@Override
	public String count(String sql) {
		return "select count(1) from (" + sql + ") t1";
	}

	@Override
	public String delete(Class<?> clazz) {
		Table table = TableHelper.getTable(clazz);
		if (StringUtils.isEmpty(table.keyColumn()))
			throw new PrimaryKeyNotDefinedException(clazz);
		return delete(clazz, table.keyColumn());
	}

	@Override
	public String delete(Class<?> clazz, String columnName) {
		return this.delete(clazz, columnName, ValueCompareType.Equal);
	}

	@Override
	public String delete(Class<?> clazz, String columnName, ValueCompareType compareType) {
		return "delete from " + TableHelper.getTable(clazz).tableName() + " where " + columnName + " "
				+ compareType.toString() + " ?";
	}

	@Override
	public String updateByMap(Class<?> clazz, Map<String, Object> columnMap, Map<String, Object> conditionMap) {
		if ((columnMap == null || columnMap.keySet().size() == 0)
				|| (conditionMap == null || conditionMap.keySet().size() == 0))
			throw new JdbcException(1000, "根据map修改时未初始化map数据");
		StringBuilder sb = new StringBuilder("update " + TableHelper.getTable(clazz).tableName() + " set ");
		int pos = 0;
		for (String key : columnMap.keySet()) {
			if (pos == 0) {
				if (columnMap.get(key) == null) {
					sb.append(key).append(" = null");
				} else
					sb.append(key).append(" = ").append(columnMap.get(key));
			} else {
				if (columnMap.get(key) == null) {
					sb.append(",").append(key).append(" = null");
				} else
					sb.append(",").append(key).append("=?");
			}
			pos++;
		}
		sb.append(" where 1=1 ");
		for (String key : conditionMap.keySet()) {
			if (conditionMap.get(key) == null) {
				sb.append(" and ").append(key).append(" is null");
			} else
				sb.append(" and ").append(key).append("=?");
		}
		return sb.toString();
	}

	@Override
	public String insert(Class<?> clazz, Map<String, Object> columnMap) {
		Table table = TableHelper.getTable(clazz);
		String sb = "insert into " + table.tableName().toLowerCase() + " (~columns~) values (~values~)";
		StringBuilder sc = new StringBuilder();
		StringBuilder sv = new StringBuilder();
		Iterator<String> ite = columnMap.keySet().iterator();
		while (ite.hasNext()) {
			String key = ite.next();
			sc.append(key + ",");
			sv.append(":" + key + ",");
		}
		if (sv.length() > 0) {
			sv.deleteCharAt(sv.length() - 1);
			sc.deleteCharAt(sc.length() - 1);
		}
		sb = sb.replaceAll("~columns~", sc.toString());
		sb = sb.replaceAll("~values~", sv.toString());
		return sb;
	}

	@Override
	public String update(Class<?> clazz, Map<String, Object> paramMap) {

		Table table = TableHelper.getTable(clazz);
		// 如果没有主键,不允许通过此方式来更新数据
		if (table.keyColumn().equals(""))
			throw new UpdateFullTableException(clazz.toString());

		String where = "";
		String sb = "update " + table.tableName().toLowerCase() + " set ~values~ ";
		StringBuilder sc = new StringBuilder();
		Iterator<String> ite = paramMap.keySet().iterator();
		while (ite.hasNext()) {
			String value = ite.next();
			boolean isKey = false;

			if (table.keyColumn().toLowerCase().equals(value.toLowerCase())) {
				if (where.length() == 0)
					where = " where " + value + "=:" + value;
				else
					where = where + " and " + value + "=:" + value;
				isKey = true;
			}
			if (!isKey)
				sc.append(value + "=:" + value + ",");
		}
		if (where.length() == 0)
			throw new UpdateFullTableException(clazz.toString());
		if (sc.length() > 0)
			sc.deleteCharAt(sc.length() - 1);
		sb = sb.replaceAll("~values~", sc.toString()) + where;
		return sb;
	}

	@Override
	public String all(Class<?> clazz) {
		return "select * from " + TableHelper.getTable(clazz).tableName();
	}

	@Override
	public String all(Class<?> clazz, QueryOrder queryOrder) {
		String s = "";
		if (queryOrder != null && queryOrder.getFields().size() > 0) {
			for (String field : queryOrder.getFields().keySet()) {
				if (!StringUtils.isEmpty(field)) {
					s = s + field + " " + queryOrder.getFields().get(field).toString() + ",";
				}
			}
			if (s.length() > 0)
				s = " order by " + s.substring(0, s.length() - 1);
		}
		return all(clazz) + s;
	}

	@Override
	public String list(Class<?> clazz, String columnName) {
		return this.list(clazz, columnName, ValueCompareType.Equal);
	}

	
	@Override
	public String list(Class<?> clazz, String columnName, QueryOrder order) {
		String s = "";
		if (order != null && order.getFields().size() > 0) {
			for (String field : order.getFields().keySet()) {
				if (!StringUtils.isEmpty(field)) {
					s = s + field + " " + order.getFields().get(field).toString() + ",";
				}
			}
			if (s.length() > 0)
				s = " order by " + s.substring(0, s.length() - 1);
		}
		return list(clazz, columnName) + s;
	}
	
	@Override
	public String list(Class<?> clazz, String columnName, ValueCompareType compareType) {
		Table table = TableHelper.getTable(clazz);
		return "select * from " + table.tableName().toLowerCase() + " where " + columnName + " "
				+ compareType.toString() + " ?";
	}

	@Override
	public String list(Class<?> clazz, String columnName, ValueCompareType compareType, QueryOrder order) {
		String s = "";
		if (order != null && order.getFields().size() > 0) {
			for (String field : order.getFields().keySet()) {
				if (!StringUtils.isEmpty(field)) {
					s = s + field + " " + order.getFields().get(field).toString() + ",";
				}
			}
			if (s.length() > 0)
				s = " order by " + s.substring(0, s.length() - 1);
		}
		return list(clazz, columnName, compareType) + s;
	}

	@Override
	public String list(Class<?> clazz, List<String> columns) {
		return this.list(clazz, columns, null);
	}

	@Override
	public String list(Class<?> clazz, List<String> columns, QueryOrder order) {
		StringBuilder sb = new StringBuilder("selec * form " + TableHelper.getTable(clazz));
		for (int index = 0; index < columns.size(); index++) {
			if (index > 0)
				sb.append(",");
			sb.append(columns.get(index) + "=?");
		}
		if (order != null && order.getFields().size() > 0) {
			String s = "";
			for (String field : order.getFields().keySet()) {
				if (!StringUtils.isEmpty(field)) {
					s = s + field + " " + order.getFields().get(field).toString() + ",";
				}
			}
			if (s.length() > 0)
				sb.append(" order by " + s.substring(0, s.length() - 1));
		}
		return sb.toString();
	}

	@Override
	public String list(Class<?> clazz, int start, int limit) {
		String sql = this.all(clazz);
		return this.list(sql, start, limit);
	}

	@Override
	public String list(Class<?> clazz, int start, int limit, QueryOrder order) {
		String sql = this.all(clazz, order);
		return this.list(sql, start, limit);
	}

	public String list(String sql, int start, int limit, QueryOrder order) {
		StringBuilder sb = new StringBuilder("");
		if (order != null && order.getFields().size() > 0) {
			String s = "";
			for (String field : order.getFields().keySet()) {
				if (!StringUtils.isEmpty(field)) {
					s = s + field + " " + order.getFields().get(field).toString() + ",";
				}
			}
			if (s.length() > 0)
				sb.append(" order by " + s.substring(0, s.length() - 1));
		}
		return this.list(sql + sb.toString(), start, limit);
	}

	public String list(Class<?> clazz, int start, int limit, String columnName) {
		return this.list(this.list(clazz, columnName), start, limit);
	}

	public String list(Class<?> clazz, int start, int limit, String columnName, QueryOrder order) {
		return this.list(clazz, start, limit, columnName, ValueCompareType.Equal, order);
	}

	@Override
	public String list(Class<?> clazz, int start, int limit, String columnName, ValueCompareType compareType) {
		return this.list(this.list(clazz, columnName, compareType), start, limit);
	}

	@Override
	public String list(Class<?> clazz, int start, int limit, String columnName, ValueCompareType compareType,
			QueryOrder order) {
		return this.list(this.list(clazz, columnName, compareType, order), start, limit);
	}

	@Override
	public String find(Class<?> clazz) {
		return this.list(clazz, TableHelper.getTable(clazz).keyColumn());
	}

	@Override
	public String deleteAll(Class<?> clazz) {
		return "delete from " + TableHelper.getTable(clazz).tableName();
	}

	@Override
	public String updateBlob(Class<?> clazz, String columnName) {
		Table table = TableHelper.getTable(clazz);
		return "update " + table.tableName().toLowerCase() + " set " + columnName + " = ? where " + table.keyColumn()
				+ "=?";
	}

	@Override
	public String queryBlob(Class<?> clazz, String columnName) {
		Table table = TableHelper.getTable(clazz);
		return "select " + columnName + " from " + table.tableName().toLowerCase() + " where " + table.keyColumn()
				+ "=?";
	}

	@Override
	public String random(Class<?> clazz, int rowCount) {
		return random(this.all(clazz), rowCount);
	}

	@Override
	public String like(String value) {
		return "%" + value + "%";
	}

	@Override
	public Table getTable(Class<?> clazz) {
		return TableHelper.getTable(clazz);
	}

}
