/*
 * Created on 2008-6-11
 */
/*        $Author: chenlingfeng7543
//        $Date: 2018/7/26 15:02
//        $Revision: 1.0
*/
package leaf.database.actions;

import com.alibaba.fastjson.JSON;
import com.hand.hap.core.impl.RequestHelper;
import com.hand.hls.excel.dto.ExcelExportInfo;
import com.hand.hls.excel.service.IExcelExportInfoService;
import com.hand.hls.utils.SpringContextHolder;
import leaf.bm.BusinessModel;
import leaf.database.DatabaseConstant;
import leaf.database.FetchDescriptor;
import leaf.database.IResultSetConsumer;
import leaf.database.service.BusinessModelService;
import leaf.database.service.BusinessModelServiceContext;
import leaf.database.service.DatabaseServiceFactory;
import org.apache.commons.lang3.StringUtils;
import uncertain.composite.CompositeMap;
import uncertain.composite.DynamicObject;
import uncertain.composite.TextParser;
import uncertain.exception.BuiltinExceptionFactory;
import uncertain.logging.ILogger;
import uncertain.logging.LoggingContext;
import uncertain.ocm.IObjectRegistry;
import uncertain.ocm.OCManager;

import java.util.List;
import java.util.regex.Matcher;

public class ModelQuery extends AbstractQueryAction {

    public final static String KEY_FILE_NAME = "_file_name_";
    public final static String KEY_FORMAT = "_format";

    String model;

    DatabaseServiceFactory svcFactory;

    BusinessModelService service;

    BusinessModelServiceContext serviceContext;

    public ModelQuery(DatabaseServiceFactory svcFactory, OCManager manager, IObjectRegistry reg) {
        super(manager, reg);
        this.svcFactory = svcFactory;
    }

    public BusinessModelService getService() {
        return service;
    }

    public DatabaseServiceFactory getServiceFactory() {
        return svcFactory;
    }

    /**
     * @return the model
     */
    public String getModel() {
        return model;
    }

    public String getName() {
        return super.getName() + "[" + getModel() + "]";
    }

    protected void doQuery(CompositeMap param, IResultSetConsumer consumer, FetchDescriptor desc)
            throws Exception {
        BusinessModel bm = service.getBusinessModel();
        if (getAttribFromRequest()) {
            if (bm.getAllowFetchAll() != null && !bm.getAllowFetchAll()) {
                fetchAll = false;
                desc.setFetchAll(fetchAll);
            }

            if (!fetchAll) {
                int maxPageSize = -1;
                if (bm.getMaxPageSize() != null) {
                    maxPageSize = bm.getMaxPageSize();
                } else {
                    Object defaultPageSize = svcFactory.getDatabaseFactory().getProperty("maxpagesize");
                    if (defaultPageSize != null)
                        maxPageSize = Integer.parseInt((String) defaultPageSize);
                }
                if (maxPageSize != -1 && desc.getPageSize() > maxPageSize && pageSize == null)
                    desc.setPageSize(maxPageSize);
            }
        }
        if ("Y".equals(param.get("__excel_export__")) && "layout.server_layout_common".equals(bm.getName())) {
//            excel导出

            StringBuffer querySql = service.getSql("query");
            int index = querySql.indexOf(":@");
            int lastIndex = 0;
            while (index > 0) {
//                可能存在${:@trx_id}
//                右边大括号
                int right = querySql.indexOf("}", index);
                int left = -1;
                int pos = index - 1;
                while (left < 0 && pos > lastIndex) {
                    char c = querySql.charAt(pos);
                    if (c == '$') {
                        left = pos;
                    } else {
                        pos--;
                    }
                }
                String fullString = querySql.substring(left, right+1);
                String valuePath = StringUtils.replaceChars(fullString, "${:}", "");
                Object object = param.getObject(valuePath);
                if (object == null) {
                    throw new RuntimeException("Can not get value from: " + valuePath);
                }
                querySql.replace(left, right+1, object.toString());

                lastIndex = index;
                index = querySql.lastIndexOf(":@");
            }
            List<CompositeMap> columns = param.getChild("_column_config_").getChild("column").getChilds();
            transfer(columns);
            String fileName = param.getString(KEY_FILE_NAME, "excel");
            String format = param.getString(KEY_FORMAT);

            ExcelExportInfo info = new ExcelExportInfo();
            info.setColumnInfo(JSON.toJSONString(columns));
            info.setSqlContent(TextParser.parse(querySql.toString().replaceAll("\\$\\{.*?}", "'$0'"), param));
            info.setStatus("NEW");
            info.setFileName(fileName);
            info.setFileType(format);
            IExcelExportInfoService service = SpringContextHolder.getBean(IExcelExportInfoService.class);
            service.insertSelective(RequestHelper.getCurrentRequest(), info);

        } else {
            service.query(param, consumer, desc);
        }
    }

    private void transfer(List<CompositeMap> list){
        if(list == null || list.size() < 1){
            return;
        }
        for (CompositeMap map : list) {
            Object column = map.getObject("column");
            if(column != null){
                CompositeMap compositeMap = (CompositeMap) column;
                List<CompositeMap> childs = compositeMap.getChilds();
                transfer(childs);
                map.put("column", childs);
            }
        }
    }

    protected void prepare(CompositeMap context)
            throws Exception {
        if (model == null)
            throw BuiltinExceptionFactory.createAttributeMissing(this, "model");
        ILogger logger = LoggingContext.getLogger(context, DatabaseConstant.LEAF_DATABASE_LOGGING_TOPIC);
        String parsed_model = TextParser.parse(model, context);
        logger.config("===================================== prepare to run model-query " + parsed_model + "==============================");
        service = svcFactory.getModelService(parsed_model, context);
        setConnectionName(service.getBusinessModel().getDataSourceName());
        /*
        SqlServiceContext
        .createSqlServiceContext(context).initConnection(svcFactory.getUncertainEngine().getObjectRegistry(), connectionName);
        */
        //service.setTrace(getTrace());    
        serviceContext = (BusinessModelServiceContext) DynamicObject.cast(context, BusinessModelServiceContext.class);
    }

    protected void cleanUp(CompositeMap context) {
    }

    /**
     * @param model the model to set
     */
    public void setModel(String model) {
        this.model = model;
    }
/*
    public String getRootPath() {
        // TODO Auto-generated method stub
        String path =  super.getRootPath();
        if(path==null)
            return service.getBusinessModel().getBaseTable();
        else
            return path;
    }
*/

    public void beginConfigure(CompositeMap config) {
        super.beginConfigure(config);
    }

}