package org.beetl.sql.core.db;

import org.beetl.sql.annotation.entity.AssignID;
import org.beetl.sql.annotation.entity.AutoID;
import org.beetl.sql.annotation.entity.SeqID;
import org.beetl.sql.clazz.kit.BeanKit;
import org.beetl.sql.core.range.RangeSql;

import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;

public class PostgresStyle extends AbstractDBStyle {
	RangeSql rangeSql = null;

	public PostgresStyle() {
		rangeSql = new PostgresRange(this);
	}

	@Override
	public int getIdType(Class c, String idProperty) {
		List<Annotation> ans = BeanKit.getAllAnnotation(c, idProperty);
		int idType = DBType.ID_AUTO; // 默认是自增长

		for (Annotation an : ans) {
			if (an instanceof SeqID) {
				idType = DBType.ID_SEQ;
				// seq 总是优先
				break;
			} else if (an instanceof AutoID) {
				idType = DBType.ID_AUTO;
				break;
			} else if (an instanceof AssignID) {
				idType = DBType.ID_ASSIGN;
			}
		}

		return idType;

	}



	@Override
	public String getName() {
		return "postgres";
	}

	@Override
	public int getDBType() {

		return DBType.DB_POSTGRES;
	}

	@Override
	public RangeSql getRangeSql() {
		return rangeSql;
	}

	@Override
	public String getSeqValue(String seqName) {
		return "nextval('" + seqName + "')";
	}

	@Override
	public String getDefaultSchema() {
		return "public";
	}

	static class PostgresRange implements RangeSql {
		PostgresStyle style;
		public PostgresRange(PostgresStyle style){
			this.style = style;
		}

		@Override
		public String toRange(String jdbcSql, Object objOffset, Long limit) {
			Long offset = ((Number)objOffset).longValue();
			offset = PageParamKit.postgresOffset(style.offsetStartZero, offset);

			int capacity = jdbcSql.length() + 50;

			StringBuilder builder = new StringBuilder(capacity);
			builder.append("select _a.* from ( ").append(jdbcSql).append(" ) _a ");
			builder.append("limit ").append(limit).append(" offset ").append(offset);
			return builder.toString();
		}

		@Override
		public String toTemplateRange(Class mapping,String template) {
			String pageSql = "select _a.* from ( \n" + template + style.getOrderBy() + " \n) _a " + " limit " + style.appendExpress(DBAutoGeneratedSql.PAGE_SIZE)
					+ " offset " + style.appendExpress(DBAutoGeneratedSql.OFFSET);
			return pageSql;
		}

		@Override
		public void addTemplateRangeParas(Map<String, Object> paras, Object objOffset, long size) {
			Long offset = (Long)objOffset;
			paras.put(DBAutoGeneratedSql.OFFSET, offset - (style.offsetStartZero ? 0 : 1));
			paras.put(DBAutoGeneratedSql.PAGE_SIZE, size);
		}
	}

}
