package org.beetl.sql.core.nosql;

import org.beetl.sql.core.ExecuteContext;
import org.beetl.sql.core.SQLManager;
import org.beetl.sql.core.db.AbstractDBStyle;
import org.beetl.sql.core.db.DBAutoGeneratedSql;
import org.beetl.sql.core.db.DBType;
import org.beetl.sql.core.db.PageParamKit;
import org.beetl.sql.core.mapping.BeanProcessor;
import org.beetl.sql.core.range.RangeSql;

import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.Map;

/**
 *  Hive
 *  遗留问题，hive的子查询结果，比如 select * from (select id from c) t,jdbc返回结果应该是id，但他返回了t.id
 *  因此HiveStyle需要重新实现BeanProcessor#getColName方法，返回正确的列名.
 *  因此不排除用户根据自己需要来重新实现getColName方法
 * @author xiandafu
 *
 */
public class HiveStyle extends AbstractDBStyle {
    RangeSql rangeSql = null;
    public HiveStyle() {
        super();
        rangeSql = new HiveRange(this);
    }

    @Override
    public int getIdType(Class c,String idProperty) {
        return DBType.ID_ASSIGN;
    }

    @Override
    public boolean  isNoSql(){
        return true;
    }
    @Override
    public String getName() {
        return "hive";
    }

    @Override
    public int getDBType() {
        return DBType.DB_HIVE;
    }

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


    /**
     *
     * @see  "https://stackoverflow.com/questions/50119180/how-to-set-range-for-limit-clause-in-hive"
     */
    static  class HiveRange implements   RangeSql{
        AbstractDBStyle sqlStyle = null;
        static String pagePrefix = "page_";
        /*需要一个排序字段 id,否则不能翻页*/
        String jdbcPageTemplate ="select * from \n" +
                "        (\n" +
                "        SELECT ccc.*,ROW_NUMBER() over (Order by ccc.id) as rowid FROM ({0}) ccc \n" +
                "        ) "+pagePrefix+" \n" +
                "    where rowid > {1} and rowid <={2}";


        public HiveRange(AbstractDBStyle style){
            this.sqlStyle = style;
        }

        /**多了一个page_前缀
         * +-----------+----------------+-------------+------------+-------------------------+--------------+
         * | page_.id  | page_.dept_no  | page_.addr  | page_.tel  |     page_.create_ts     | page_.rowid  |
         * +-----------+----------------+-------------+------------+-------------------------+--------------+
         * | 1         | 1              | ??          | 1800       | 2020-08-26 00:00:00.0   | 1            |
         * | 1         | 1              | ??          | 1800       | 2020-08-26 13:29:29.11  | 2            |
         * +-----------+----------------+-------------+------------+-------------------------+--------------+
         * @param jdbcSql
         * @param objOffset 起始位置，对于mysql等传统数据库有语法支持，但对hive等可能没有此参数，但offset可以作为其他参数做相对位置
         * @param limit
         * @return
         */

        @Override
        public String toRange(String jdbcSql, Object objOffset , Long limit) {
            Long offset = ((Number)objOffset).longValue();
            offset = PageParamKit.mysqlOffset(sqlStyle.offsetStartZero, offset);
            String sql = MessageFormat.format(jdbcPageTemplate,jdbcSql,offset,limit+offset);
            return sql;
        }

        @Override
        public String toTemplateRange(Class mapping,String template) {
            String orderBySql =  template + sqlStyle.getOrderBy();
            String sql = MessageFormat.format(jdbcPageTemplate,orderBySql,sqlStyle.appendExpress( DBAutoGeneratedSql.OFFSET ),
                    sqlStyle.appendExpress( DBAutoGeneratedSql.PAGE_SIZE ));
            return sql;
        }

        @Override
        public void addTemplateRangeParas(Map<String, Object> paras, Object objOffset, long size) {
            Long offset = (Long)objOffset;
            offset = PageParamKit.mysqlOffset(sqlStyle.offsetStartZero, offset);
            paras.put(DBAutoGeneratedSql.OFFSET, offset);
            paras.put(DBAutoGeneratedSql.PAGE_SIZE, offset+size);
        }
    }


    /**
     * 对java.util.Date识别映射
     * 对返回的列名去掉翻页前缀
     * @param sqlManager
     */
    @Override
    public void config(SQLManager sqlManager){

        sqlManager.setDefaultBeanProcessors( new BeanProcessor(){
            @Override
            protected  String getColName(ExecuteContext ctx, ResultSetMetaData rsmd, int col) throws SQLException{
               String colName = super.getColName(ctx,rsmd,col);
               if(ctx.sqlId.isPage()){
                   colName = colName.replaceFirst(HiveRange.pagePrefix+".","");
               }
               return colName;
            }
        });
    }




}
