package org.springblade.common.utils;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
import com.baomidou.mybatisplus.extension.kotlin.KtQueryChainWrapper;
import com.baomidou.mybatisplus.extension.kotlin.KtUpdateChainWrapper;
import org.springblade.core.mp.base.BaseEntity;
import org.springblade.core.mp.base.BaseService;
import org.springblade.core.tenant.annotation.TenantIgnore;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * @Author: Silent
 * @Description 使用该对象去调用BaseService方法可以忽略租户
 * @Date: Created in 15:49 2021/10/12
 * @Modified By:
 */
@Component
@TenantIgnore
public class TenantIgnoreUtil<T extends BaseService<E>,E extends BaseEntity> {

	@TenantIgnore
	public boolean deleteLogic(T t, @NotEmpty List ids) {
		return t.deleteLogic(ids);
	}

	@TenantIgnore
	public boolean changeStatus(T t, @NotEmpty List ids, Integer status) {
		return t.changeStatus(ids, status);
	}

	@TenantIgnore
	public boolean save(T t, E entity) {
		return t.save(entity);
	}

	@TenantIgnore
	public boolean saveBatch(T t, Collection entityList) {
		return t.saveBatch(entityList);
	}

	@TenantIgnore
	public boolean saveBatch(T t, Collection entityList, int batchSize) {
		return t.saveBatch(entityList, batchSize);
	}

	@TenantIgnore
	public boolean saveOrUpdateBatch(T t, Collection entityList) {
		return t.saveOrUpdateBatch(entityList);
	}

	@TenantIgnore
	public boolean saveOrUpdateBatch(T t, Collection entityList, int batchSize) {
		return t.saveOrUpdateBatch(entityList, batchSize);
	}

	@TenantIgnore
	public boolean removeById(T t, Serializable id) {
		return t.removeById(id);
	}

	@TenantIgnore
	public boolean remove(T t, Wrapper queryWrapper) {
		return t.remove(queryWrapper);
	}

	@TenantIgnore
	public boolean updateById(T t, E entity) {
		return t.updateById(entity);
	}

	@TenantIgnore
	public boolean update(T t, Wrapper updateWrapper) {
		return t.update(updateWrapper);
	}

	@TenantIgnore
	public boolean update(T t, E entity, Wrapper updateWrapper) {
		return t.update(entity, updateWrapper);
	}

	@TenantIgnore
	public boolean updateBatchById(T t, Collection entityList) {
		return t.updateBatchById(entityList);
	}

	@TenantIgnore
	public boolean removeByIds(T t, Collection idList) {
		return t.removeByIds(idList);
	}

	@TenantIgnore
	public boolean removeByMap(T t, Map columnMap) {
		return t.removeByMap(columnMap);
	}

	@TenantIgnore
	public boolean updateBatchById(T t, Collection entityList, int batchSize) {
		return t.updateBatchById(entityList, batchSize);
	}

	@TenantIgnore
	public boolean saveOrUpdate(T t, E entity) {
		return t.saveOrUpdate(entity);
	}

	@TenantIgnore
	public E getById(T t, Serializable id) {
		return t.getById(id);
	}

	@TenantIgnore
	public E getOne(T t, Wrapper<E> queryWrapper) {
		return t.getOne(queryWrapper);
	}

	@TenantIgnore
	public List listByMap(T t, Map columnMap) {
		return t.listByMap(columnMap);
	}

	@TenantIgnore
	public List listByIds(T t, Collection idList) {
		return t.listByIds(idList);
	}

	@TenantIgnore
	public E getOne(T t, Wrapper<E> queryWrapper, boolean throwEx) {
		return t.getOne(queryWrapper, throwEx);
	}

	@TenantIgnore
	public Map<String, Object> getMap(T t, Wrapper<E> queryWrapper) {
		return t.getMap(queryWrapper);
	}

	@TenantIgnore
	public int count(T t) {
		return t.count();
	}

	@TenantIgnore
	public int count(T t, Wrapper queryWrapper) {
		return t.count(queryWrapper);
	}

	@TenantIgnore
	public List list(T t, Wrapper queryWrapper) {
		return t.list(queryWrapper);
	}

	@TenantIgnore
	public List list(T t) {
		return t.list();
	}

	@TenantIgnore
	public List<Map<String, Object>> listMaps(T t, Wrapper queryWrapper) {
		return t.listMaps(queryWrapper);
	}

	@TenantIgnore
	public List<Map<String, Object>> listMaps(T t) {
		return t.listMaps();
	}

	@TenantIgnore
	public List<Object> listObjs(T t) {
		return t.listObjs();
	}

	@TenantIgnore
	public List<E> listObjs(T t, Wrapper queryWrapper) {
		return t.listObjs(queryWrapper);
	}

	@TenantIgnore
	public <P extends IPage<Map<String, Object>>> P pageMaps(T t, P page) {
		return t.pageMaps(page);
	}

	@TenantIgnore
	public <P extends IPage<Map<String, Object>>> P pageMaps(T t, P page, Wrapper<E> queryWrapper) {
		return t.pageMaps(page, queryWrapper);
	}

	@TenantIgnore
	public List listObjs(T t, Wrapper queryWrapper, Function mapper) {
		return t.listObjs(queryWrapper, mapper);
	}

	@TenantIgnore
	public List listObjs(T t, Function mapper) {
		return t.listObjs(mapper);
	}

	@TenantIgnore
	public <P extends IPage<E>> P page(T t, P page) {
		return t.page(page);
	}

	@TenantIgnore
	public <P extends IPage<E>> P page(T t, P page, Wrapper<E> queryWrapper) {
		return t.page(page, queryWrapper);
	}

	@TenantIgnore
	public BaseMapper getBaseMapper(T t) {
		return t.getBaseMapper();
	}

	@TenantIgnore
	public Class getEntityClass(T t) {
		return t.getEntityClass();
	}

	@TenantIgnore
	public QueryChainWrapper query(T t) {
		return t.query();
	}

	@TenantIgnore
	public LambdaQueryChainWrapper lambdaQuery(T t) {
		return t.lambdaQuery();
	}

	@TenantIgnore
	public KtQueryChainWrapper ktQuery(T t) {
		return t.ktQuery();
	}

	@TenantIgnore
	public KtUpdateChainWrapper ktUpdate(T t) {
		return t.ktUpdate();
	}

	@TenantIgnore
	public UpdateChainWrapper update(T t) {
		return t.update();
	}

	@TenantIgnore
	public LambdaUpdateChainWrapper lambdaUpdate(T t) {
		return t.lambdaUpdate();
	}

	@TenantIgnore
	public boolean saveOrUpdate(T t, E entity, Wrapper updateWrapper) {
		return t.saveOrUpdate(entity, updateWrapper);
	}

	@TenantIgnore
	public Object getObj(T t, Wrapper<E> queryWrapper, Function mapper) {
		return t.getObj(queryWrapper, mapper);
	}

	/**
	 * 通过反射代理执行
	 * @param t
	 * @param funName
	 * @param tClass
	 * @param Es
	 * @return
	 */
	@TenantIgnore
	public Object invoke(T t,String funName,Class<T> tClass,Object... Es){
		try {
			Method declaredMethod = t.getClass().getDeclaredMethod(funName,tClass);
			return declaredMethod.invoke(t,Es);
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return null;
	}

	@TenantIgnore
	public Object invoke(T t,Method method,Object... Es){
		try {
			return method.invoke(t,Es);
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		return null;
	}
}
