package com.its.vds.dao.mapper;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Data
@Slf4j
public abstract class BatchDaoService {

    protected final int MAX_BATCH_SIZE = 1000;

    protected final SqlSessionFactory sqlSessionFactory;
    protected String serviceName;
    protected int count;

    public BatchDaoService(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    public int getCount() {
        return this.count;
    }

    public int execute(String mapperName) {
        int total = 0;
        SqlSession sqlSession = null;
        try {
            sqlSession = this.sqlSessionFactory.openSession(ExecutorType.SIMPLE, false);
            total = sqlSession.update(mapperName);
        }
        finally {
            if (sqlSession != null) {
                sqlSession.commit();
                sqlSession.close();
            }
        }
        return total;
    }

    public int insertBatch(String mapperName, List<HashMap<String, Object>> lists) {
        int total = lists.size();
        if (total == 0) {
            log.info("[BATCH--DAO] {}:insertBatch: {}: No Data.", this.serviceName, mapperName);
            return 0;
        }
        int jobCnt = 0;
        SqlSession sqlSession = null;
        try {
            sqlSession = this.sqlSessionFactory.openSession(ExecutorType.BATCH, false);
            for (Map<String, Object> param : lists) {
                sqlSession.insert(mapperName, param);
                jobCnt++;
                if (jobCnt % this.MAX_BATCH_SIZE == 0 || jobCnt == total) {
                    sqlSession.flushStatements();
                    sqlSession.clearCache();
                }
            }
        }
        finally {
            if (sqlSession != null) {
                sqlSession.commit();
                sqlSession.close();
            }
        }
        this.count = total;
        return this.count;
    }

    public int updateBatch(String mapperName, List<HashMap<String, Object>> lists) {
        int total = lists.size();
        if (total == 0) {
            log.info("[BATCH--DAO] {}:updateBatch: {}: No Data.", this.serviceName, mapperName);
            return 0;
        }
        int jobCnt = 0;
        SqlSession sqlSession = null;
        try {
            sqlSession = this.sqlSessionFactory.openSession(ExecutorType.BATCH, false);
            for (Map<String, Object> param : lists) {
                sqlSession.update(mapperName, param);
                jobCnt++;
                if (jobCnt % this.MAX_BATCH_SIZE == 0 || jobCnt == total) {
                    sqlSession.flushStatements();
                    sqlSession.clearCache();
                }
            }
        }
        finally {
            if (sqlSession != null) {
                sqlSession.commit();
                sqlSession.close();
            }
        }
        this.count = total;
        return this.count;
    }

}
