package com.cnd3b.common.data.RowsPool;

import com.cnd3b.common.BaseClass;
import com.cnd3b.common.data.Rows;
import com.cnd3b.common.data.RowsMap;
import com.cnd3b.common.data.SQLFactory;
import com.cnd3b.common.data.db.DBConnect;

import java.util.*;

public class RowsPool extends BaseClass {

    public enum GroupName {
        /**
         * 下级业务员
         */
        USER_SUBUSER,

    }

    //站点-表名-RowsMap
    private static HashMap<String, HashMap<GroupName, RowsMap>> rowspool = new HashMap<>();
    //站点-表名-关键字段-数据有效时间
    private static HashMap<String, HashMap<GroupName, HashMap<String, Date>>> rowspoolCtrl = new HashMap<>();
    /**
     * 缓存有效时间，分钟
     */
    public static int datalife = 30;
    /**
     * 缓存统一清理时间，分钟
     */
    public static int cleandatatime = 60;

    public static Date nextAutoRemoveTime = null;
    public static boolean debugOpen = true;


    public static Rows getRows(String siteid, GroupName groupName, String rowsMapKey) {
        return getRowsMap(siteid, groupName, rowsMapKey).get(rowsMapKey);
    }

    public static RowsMap getRowsMap(String siteid, GroupName groupName, String rowsMapKey) {
        return getRowsMap(siteid, groupName, new String[]{rowsMapKey});
    }

    public static RowsMap getRowsMap(String siteid, GroupName groupName, String[] rowsMapKeys) {
        init(siteid, groupName);
        Query(siteid, groupName, rowsMapKeys);
        return rowspool.get(siteid).get(groupName);
    }

    private void query(String siteid, GroupName groupName, String where) {
        DBConnect dbConnect = new DBConnect();
        RowsMap rowsmap = null;
        if (groupName == GroupName.USER_SUBUSER) {
            SQLFactory sqlFactory = new SQLFactory(this, "下属业务员账号列表查询");
            sqlFactory.addParameter_SQL("userid", where);
            sqlFactory.addParameter("siteid", siteid);
            rowsmap = dbConnect.runSqlQuery(sqlFactory.getSQL()).toRowsMap("fitemno");
        }
        if (rowsmap != null && !rowsmap.isEmpty()) {
            saveRowsToPool(siteid, groupName, rowsmap);
        }
    }

    private static void Query(String siteid, GroupName groupName, String[] rowsMapKeys) {
        StringBuffer wherestr = new StringBuffer();
        int i = 0;
        for (String rowsMapKey : rowsMapKeys) {
            boolean isneedtoquery = false;
            if (!rowspoolCtrl.get(siteid).get(groupName).containsKey(rowsMapKey)) {
                isneedtoquery = true;
            } else if (rowspoolCtrl.get(siteid).get(groupName).get(rowsMapKey).before(Calendar.getInstance().getTime())) {
                isneedtoquery = true;
            } else if (!rowspool.get(siteid).get(groupName).containsKey(rowsMapKey)) {
                isneedtoquery = true;
            }
            if (isneedtoquery) {
                i++;
                if (wherestr.toString().equals("")) {
                    wherestr.append("'").append(rowsMapKey).append("'");
                } else {
                    wherestr.append(",'").append(rowsMapKey).append("'");
                }
            }
        }

        if (!wherestr.toString().equals("")) {
            new RowsPool().query(siteid, groupName, "(" + wherestr.toString() + ")");
            autoRemove();
        }
        if (debugOpen) {
            System.err.println("RowsPool缓存:本次查询" + groupName + "共" + rowsMapKeys.length + "条，其中" + (rowsMapKeys.length - i) + "条从缓存获取,现有缓存共" + rowspool.get(siteid).get(groupName).size() + "条");
        }
    }


    private void saveRowsToPool(String siteid, GroupName groupName, RowsMap rowsmap) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) + datalife);

        for (String fitemno : rowsmap.keySet()) {
            if (debugOpen) {
                System.err.println("RowsPool缓存:" + siteid + "-" + groupName + ":" + fitemno);
            }
            rowspool.get(siteid).get(groupName).put(fitemno, rowsmap.get(fitemno));
            rowspoolCtrl.get(siteid).get(groupName).put(fitemno, calendar.getTime());
        }
    }


    private static void autoRemove() {
        if (nextAutoRemoveTime.before(Calendar.getInstance().getTime())) {

            Date nowdate = Calendar.getInstance().getTime();
            for (String siteid : rowspoolCtrl.keySet()) {
                for (GroupName groupName : rowspoolCtrl.get(siteid).keySet()) {

                    Iterator<String> rowsMapKeyit = rowspoolCtrl.get(siteid).get(groupName).keySet().iterator();
                    ArrayList<String> rowsMapKeylist = new ArrayList<>();
                    while (rowsMapKeyit.hasNext()) {
                        rowsMapKeylist.add(rowsMapKeyit.next());
                    }
                    for (String rowsMapKey : rowsMapKeylist) {
                        if (rowspoolCtrl.get(siteid).get(groupName).containsKey(rowsMapKey) && rowspoolCtrl.get(siteid).get(groupName).get(rowsMapKey).before(nowdate)) {
                            remove(siteid, groupName, rowsMapKey);
                        }
                    }
                }
            }
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MINUTE, cleandatatime);
            nextAutoRemoveTime = calendar.getTime();
        }
    }

    private static void remove(String siteid, GroupName groupName, String fitemno) {
        synchronized (RowsPool.class) {
            rowspoolCtrl.get(siteid).get(groupName).remove(fitemno);
            rowspool.get(siteid).get(groupName).remove(fitemno);
        }
    }


    private static void init(String siteid, GroupName groupName) {
        if (!rowspool.containsKey(siteid)) {
            rowspool.put(siteid, new HashMap<>());
        }
        if (!rowspool.get(siteid).containsKey(groupName)) {
            rowspool.get(siteid).put(groupName, new RowsMap());
        }
        if (!rowspoolCtrl.containsKey(siteid)) {
            rowspoolCtrl.put(siteid, new HashMap<>());
        }
        if (!rowspoolCtrl.get(siteid).containsKey(groupName)) {
            rowspoolCtrl.get(siteid).put(groupName, new HashMap<>());
        }
        if (nextAutoRemoveTime == null) {
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MINUTE, cleandatatime);
            nextAutoRemoveTime = calendar.getTime();
        }
    }
}
