/**
 * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
 */
package com.jeeplus.core.persistence.dialect.db;

import com.jeeplus.core.persistence.dialect.Dialect;
import org.apache.commons.lang3.StringUtils;

/**
 * MSSQLServer 数据库实现分页方言
 *
 * @author poplar.yfyang
 * @version 1.0 2010-10-10 下午12:31
 * @since JDK 1.5
 */
public class SQLServerDialect implements Dialect {

    public boolean supportsLimit() {
        return true;
    }

    static int getAfterSelectInsertPoint(String sql) {
        int selectIndex = sql.toLowerCase().indexOf("select");
        final int selectDistinctIndex = sql.toLowerCase().indexOf("select distinct");
        return selectIndex + (selectDistinctIndex == selectIndex ? 15 : 6);
    }

    public String getLimitString(String sql, int offset, int limit) {
        return getLimit(sql, offset, limit);
    }

    public String getCountString(String sql) {
        return new StringBuffer(sql.length() + 8)
                .append(sql)
                .insert(getAfterSelectInsertPoint(sql), " top 100 percent ")
                .toString();
    }

    static String getOrderByPart(String sql) {
        String loweredString = sql.toLowerCase();
        int orderByIndex = loweredString.indexOf("order by");
        if (orderByIndex != -1) {
            // if we find a new "order by" then we need to ignore
            // the previous one since it was probably used for a subquery
            return sql.substring(orderByIndex);
        } else {
            return "";
        }
    }

    public String getLimit(String querySqlString, int offset, int limit) {
        {
            StringBuilder pagingBuilder = new StringBuilder();
            String orderby = getOrderByPart(querySqlString);
            String distinctStr = "";

            String loweredString = querySqlString.toLowerCase();
            String sqlPartString = querySqlString;
            if (loweredString.trim().startsWith("select")) {
                int index = 6;
                if (loweredString.startsWith("select distinct")) {
                    distinctStr = "DISTINCT ";
                    index = 15;
                }
                sqlPartString = sqlPartString.substring(index);
            }
            pagingBuilder.append(sqlPartString);

            // if no ORDER BY is specified use fake ORDER BY field to avoid errors
            if (StringUtils.isEmpty(orderby)) {
                orderby = "ORDER BY CURRENT_TIMESTAMP";
            }

            StringBuilder result = new StringBuilder();
            result.append("WITH query AS (SELECT ")
                    .append(distinctStr)
                    .append("TOP 100 PERCENT ")
                    .append(" ROW_NUMBER() OVER (")
                    .append(orderby)
                    .append(") as __row_number__, ")
                    .append(pagingBuilder)
                    .append(") SELECT * FROM query WHERE __row_number__ BETWEEN ")
                    .append(offset+1).append(" AND ").append(offset + limit)
                    .append(" ORDER BY __row_number__");

            return result.toString();
        }
    }


}
