package com.hzya.frame.basedao.dao;

import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.github.pagehelper.PageInfo;
import com.hzya.frame.page.PageAttribute;
import com.hzya.frame.page.PageHelper;
import com.hzya.frame.web.entity.BaseEntity;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

/**
 * @author Administrator
 */
@Component
public abstract class MybatisGenericDao<E extends Serializable, PK extends Serializable> implements IBaseDao<E, PK> {
    public static final String POSTFIX_INSERT = "_insert";
    public static final String POSTFIX_UPDATE = "_update";
    public static final String POSTFIX_UPDATE_SELECTIVE = "_updateSelective";
    public static final String POSTFIX_LOGIC_DELETE = "_logicDelete";
    public static final String POSTFIX_LOGIC_DELETE_LOGICDELETE_MULTI_CONDITION = "_logicDelete_Multi_Condition";
    public static final String POSTFIX_DELETE = "_delete";
    public static final String POSTFIX_DELETE_MULTI_CONDITION = "_delete_Multi_Condition";
    public static final String POSTFIX_DELETE_BYKEY = "_deleteByPrimaryKey";
    public static final String POSTFIX_GET = "_get";
    public static final String POSTFIX_SELECT = "_list";
    public static final String POSTFIX_COUNT = "_count";
    public static final String POSTFIX_CUSTOM1 = "_custom1";
    public static final String POSTFIX_CUSTOM2 = "_custom2";
    public static final String POSTFIX_CUSTOM3 = "_custom3";
    private static final Log LOG = LogFactory.getLog(MybatisGenericDao.class);

    @Resource
    private SqlSession sqlSession;
    private Class<?> entityClass;

    public MybatisGenericDao() {
        Class<?> c = super.getClass();
        Type t = c.getGenericSuperclass();
        if (t instanceof ParameterizedType) {
            this.entityClass = ((Class<?>) ((ParameterizedType) t).getActualTypeArguments()[0]);
            //LOG.info("enityClass : " + this.entityClass.toString());
        }
    }

    public String getSqlIdPrifx() {
        String path = this.getClass().getName() + ".";
        return path;
    }


    @Override
    public Object selectOne(String id, Object param) {
        return this.sqlSession.selectOne(id, param);
    }

//    @DS("#param.dataSourceCode")
    @Override
    public List<?> selectList(String id, Object param) {
        return this.sqlSession.selectList(id, param);
    }

    @Override
    public List<E> queryByLike(E o) {
        List<E> tempList = this.sqlSession.selectList(getSqlIdPrifx() + "entity_list_like", o);
        return tempList;
    }

    @Override
    public List<E> queryByOr(E o) {
        List<E> tempList = this.sqlSession.selectList(getSqlIdPrifx() + "entity_list_or", o);
        return tempList;
    }

    @Override
    public E get(PK id) {
        Assert.notNull(id, "get: ID不能为null");
        Object o = this.sqlSession.selectOne(getSqlIdPrifx() + "entity_get", id);
        return (E) o;
    }

    @DS("#o.dataSourceCode")
    @Override
    public E query(E o, String stamentID) {
        return (E) this.sqlSession.selectOne(stamentID, o);
    }

    @Override
    public List<E> queryList(E o, String stamentID) {
        List<E> tempList = this.sqlSession.selectList(stamentID, o);
        return tempList;
    }

    @Override
    public List<E> queryBase(E o) {
        List<E> tempList = this.sqlSession.selectList(getSqlIdPrifx() + "entity_list_base", o);
        return tempList;
    }

    @Override
    public List<E> getAll() {
        List tempList = this.sqlSession.selectList(getSqlIdPrifx() + "entity_list_base");
        return tempList;
    }

    @Override
    @DS("#param.dataSourceCode")
    public List<E> query(Serializable param) {
        String str = getSqlIdPrifx() + "entity_list_base";
        List<E> tempList = this.sqlSession.selectList(str, param);
        return tempList;
    }

    public E selectOne(Serializable param) {
        String str = getSqlIdPrifx() + "entity_list_base";
        E e = this.sqlSession.selectOne(str, param);
        return e;
    }

    @Override
    public E saveOrUpdate(E o) {
        Assert.notNull(o, "saveOrUpdate : 参数列表不能为NULL");
        Object id = null;
        try {
            id = BeanUtils.getProperty(o, "id");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        if ((id == null) || ("".equals(String.valueOf(id)))) {
            this.sqlSession.insert(getSqlIdPrifx() + "entity_insert", o);
        } else {
            this.sqlSession.update(getSqlIdPrifx() + "entity_update", o);
        }

        return o;
    }
    @DS("#o.dataSourceCode")
    @Override
    public E queryOne(E o) {
        E e = selectOne(o);
        return e;
    }

    @Override
    public E update(E o) {
        Assert.notNull(o, "update : 参数列表不能为NULL");
        this.sqlSession.update(getSqlIdPrifx() + "entity_update", o);
        return o;
    }

    @Override
    public E save(E o) {
        Assert.notNull(o, "save : 参数列表不能为NULL");
        this.sqlSession.insert(getSqlIdPrifx() + "entity_insert", o);
        return o;
    }

    @Override
    public Integer insert(String paramString, Object paramE) {
        return this.sqlSession.insert(paramString, paramE);
    }

    @Override
    public E save(String id, E param) {
        this.sqlSession.insert(id, param);
        return param;
    }

    @Override
    public int logicRemove(E o) {
        Assert.notNull(o, "logicRemove : 参数列表不能为NULL");
        return this.sqlSession.update(getSqlIdPrifx() + "entity_logicDelete", o);
    }

    @Override
    public int logicRemoveMultiCondition(E o) {
        Assert.notNull(o, "logicRemoveMultiCondition : 参数列表不能为NULL");
        return this.sqlSession.update(getSqlIdPrifx() + "entity_logicDelete_Multi_Condition", o);
    }

    @Override
    public int logicRemoveMultiCondition(String id, E o) {
        return this.sqlSession.update(id, o);
    }

    public int removeById(PK id) {
        Assert.notNull(id, "removeById : 参数列表不能为NULL");
        int result = this.sqlSession.delete(getSqlIdPrifx() + "entity_delete", id);

        return result;
    }

    public int remove(String id, Object param) {
        return this.sqlSession.update(id, param);
    }

    @Override
    public int delete(String id, Object param) {
        return this.sqlSession.delete(id, param);
    }

    @Override
    public int update(String id, Object param) {
        return this.sqlSession.update(id, param);
    }

    @Override
    public PageAttribute<E> queryPaged(Object baseEntity) {
        String sqlId = getSqlIdPrifx() + "entity_list_like";
        return queryPaged(sqlId, baseEntity);
    }

    /**
     * 分页查询
     */
    @Override
    public PageAttribute<E> queryPaged(String statement, Object baseEntity) {
        Assert.notNull(statement, "queryPaged ID 不能为NULL");
        Assert.notNull(baseEntity, "queryPaged baseEntity :参数列表不能为NULL");
        BaseEntity realEntity = (BaseEntity) baseEntity;
        Long rowsParam = realEntity.getRows();
        Long pageParam = realEntity.getPage();
        Long limitParam = realEntity.getLimit();
        Long offsetParam = realEntity.getOffset();
        int page = 1;
        int rows = 10;

        try {
            if (rowsParam != null) {
                rows = rowsParam.intValue();
            } else if (limitParam != null) {
                rows = limitParam.intValue();
            }

            if (pageParam != null) {
                page = pageParam.intValue();
            } else if (offsetParam != null) {
                page = offsetParam.intValue() / rows + 1;
            }
        } catch (Exception var12) {
            var12.printStackTrace();
        }
        PageHelper.startPage(page, rows);
        if (StrUtil.isEmpty(realEntity.getDialect_type())) {
            PageHelper.dialect_type.set(PageHelper.MYSQL);
        } else {
            PageHelper.dialect_type.set(realEntity.getDialect_type());
        }
        PageHelper.startPage(page, rows);
        List<E> list = this.query(statement, baseEntity);
        PageAttribute pageInfo = new PageAttribute(list);
        return pageInfo;
    }

    public List<E> query(String statement, Object baseEntity) {
        Assert.notNull(statement, "query :ID 不能为NULL");
        Assert.notNull(baseEntity, "query baseEntity :不能为NULL");
        List<E> list = this.sqlSession.selectList(statement, baseEntity);
        return list;
    }

    @Override
    public Integer getCount(String statement,Object baseEntity) {
        Integer totalCount = this.sqlSession.selectOne(statement, baseEntity);
        return totalCount;
    }
    public List<E> query(Object baseEntity) {

        Assert.notNull(baseEntity, "query baseEntity :不能为NULL");
        List<E> list = this.sqlSession.selectList(getSqlIdPrifx() + "entity_list_like", baseEntity);
        return list;
    }

    @Override
    public Integer getCount(E paramE) {
        Integer totalCount = this.sqlSession.selectOne(getSqlIdPrifx() + "entity_count", paramE);
        return totalCount;
    }

    @Override
    public int delete(PK id) {
        return this.sqlSession.delete(getSqlIdPrifx() + "entity_delete", id);
    }

    @Override
    public boolean checkRepeated(E o) {
//        Class TargetClass;
//        try {
//            TargetClass = o.getClass();
//            List fieldList = UtilHelper.getPrimaryNameList(TargetClass);
//            String id = BeanUtils.getProperty(o, "id");
//            boolean flag = true;
//            if (fieldList == null)
//                return false;
//
//            Object param = org.springframework.beans.BeanUtils.instantiate(TargetClass);
//            for (int i = 0; i < fieldList.size(); ++i) {
//                Field field = (Field) fieldList.get(i);
//                String name = field.getName();
//                Object tempVal = BeanUtils.getProperty(o, name);
//                if ((tempVal != null) && (!("".equals(tempVal)))) {
//                    flag = false;
//                    BeanUtils.setProperty(param, name, BeanUtils.getProperty(o, name));
//                }
//
//            }
//
//            if (flag)
//                return false;
//
//            List resultList = query((Serializable) param);
//            if ((resultList != null) && (resultList.size() > 0)) {
//                if ((id == null) || ("".equals(id)))
//                    return true;
//
//                Object tempResult = resultList.get(0);
//                String tempId = BeanUtils.getProperty(tempResult, "id");
//
//                return (!(tempId.equals(id)));
//            }
//
//            return false;
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        return false;
    }

}
