package net.wicp.tams.duckula.ops.pages;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.tuple.MutableTriple;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.util.TextStreamResponse;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import cn.hutool.core.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import net.wicp.tams.common.Result;
import net.wicp.tams.common.annotation.TamsBean;
import net.wicp.tams.common.apiext.ReflectAssist;
import net.wicp.tams.common.apiext.StringUtil;
import net.wicp.tams.common.apiext.json.EasyUiAssist;
import net.wicp.tams.common.callback.IConvertValue;
import net.wicp.tams.component.tools.TapestryAssist;
import net.wicp.tams.duckula.ops.WebTools;

@Slf4j
public abstract class ParentPageBean<T> extends ParentPage {
	@SuppressWarnings("unchecked")
	public Class<T> getTClass() {
		Class<T> tClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
				.getActualTypeArguments()[0];
		return tClass;
	}

	@SuppressWarnings("rawtypes")
	protected MutableTriple<String, String[], Map<String, IConvertValue>> queryAssetInfo = EasyUiAssist
			.getQueryAssetInfo(getTClass());

	protected Pair<List<Field>, List<Field>> querySaveInfo = EasyUiAssist.getQuerySaveInfo(getTClass());

	@Property
	private String cols = queryAssetInfo.left;

	@Property
	private TamsBean tamsbean = getTClass().getAnnotation(TamsBean.class);

	protected final T t = TapestryAssist.getBeanFromPage(getTClass(), requestGlobals);

	public TextStreamResponse onSave() {
		final T saveBean = TapestryAssist.getBeanFromPage(getTClass(), requestGlobals);
		String id = request.getParameter("id");
		boolean isInsert = false;
		if (StringUtil.isNull(id)) {
			isInsert = true;
		} else {
			isInsert = false;
		}
		try {
			doSave(saveBean, isInsert);
		} catch (Throwable e) {
			log.error("save data error", e);
			return TapestryAssist.getTextStreamResponse(Result.getError(e.getMessage()));
		}
		return TapestryAssist.getTextStreamResponse(Result.getSuc());
	}

	public TextStreamResponse onDel() {
		String id = request.getParameter("id");
		if (StringUtil.isNull(id)) {
			return TapestryAssist.getTextStreamResponse(Result.getSuc("没有拿到id，不能进行删除"));
		}
		try {
			doDel(id);
		} catch (Throwable e) {
			log.error("delete data error", e);
			return TapestryAssist.getTextStreamResponse(Result.getError(e.getMessage()));
		}
		return TapestryAssist.getTextStreamResponse(Result.getSuc());
	}

	public String getUrl() {
		String retUrl = tamsbean.url();
		if (StringUtil.isNull(retUrl)) {
			// 页面所在的类名
			String name = getClass().getName();
			String initParameter = servletContext.getInitParameter("tapestry.app-package");
			retUrl = name.replace(initParameter + ".pages", "").replace(".", "/");
		}
		return retUrl;
	}

	public abstract void doSave(T t, boolean isInsert);

	public abstract void doDel(String id);

	////////////////////////////////////////////////////////////// mytatis特有的/////////////////////////////////////////////////////////////////////////////////
	public abstract BaseMapper<T> getBaseMapper();

	public abstract void packageQuery(T t, QueryWrapper<T> queryWrapper);

	@SuppressWarnings("rawtypes")
	protected Pair<String[], Map<String, IConvertValue>> packageConvert() {
		return Pair.of(this.queryAssetInfo.middle, this.queryAssetInfo.right);
	};

	@SuppressWarnings("rawtypes")
	public TextStreamResponse onQuery() {
		final T t = TapestryAssist.getBeanFromPage(getTClass(), requestGlobals);
		QueryWrapper<T> queryWrapper = new QueryWrapper<T>();
		this.packageQuery(t, queryWrapper);// 组装查询
		BaseMapper<T> mapper = getBaseMapper();
		Pair<List<T>, Long> query = this.query(mapper, queryWrapper);
		// Pair<List<SysUser>, Long> query = doQuery(t, queryWrapper);
		Pair<String[], Map<String, IConvertValue>> packageConvert = packageConvert();
		String retstr = EasyUiAssist.getJsonForGridAlias2(query.getLeft(), packageConvert.getLeft(),
				packageConvert.getRight(), query.getRight());
		return TapestryAssist.getTextStreamResponse(retstr);
	}

	/***
	 * mybatis查询封装
	 * 
	 * @param <T>          mybatis的po
	 * @param mapper       mybatis的mapper
	 * @param queryWrapper mybatis的查询封装
	 * @return L：数据，R:数据的总量
	 */
	public <T> Pair<List<T>, Long> query(BaseMapper<T> mapper, QueryWrapper<T> queryWrapper) {
		String needpage = request.getParameter("needpage");
		boolean isPage = StringUtil.isNotNull(needpage) && !Boolean.parseBoolean(needpage) ? false : true;
		List<T> selectList = null;
		long size = 0;
		if (isPage) {// 需要分页，默认
			Page<T> selectPage = mapper.selectPage(WebTools.buildPage(request), queryWrapper);
			selectList = selectPage.getRecords();
			size = selectPage.getTotal();
		} else {
			selectList = mapper.selectList(queryWrapper);
			size = selectList.size();
		}
		return Pair.of(selectList, size);
	}

	/***
	 * 保存或修改对象
	 * 
	 * @param <T>
	 * @param mapper
	 * @param tClass
	 * @return
	 */
	public TextStreamResponse saveCommon(BaseMapper<T> mapper, IUpdateObj<T> callback) {
		final T po = TapestryAssist.getBeanFromPage(getTClass(), requestGlobals);
		if (callback != null) {
			callback.doUpdate(po, BeanUtil.getFieldValue(po, "id") == null);
		}
		if (BeanUtil.getFieldValue(po, "id") == null) {
			mapper.insert(po);
		} else {
			ReflectAssist.invokeMothed(mapper, "updateByPrimaryKeySelective", po);
		}
		return TapestryAssist.getTextStreamResponse(Result.getSuc());
	}

	public TextStreamResponse saveCommon(BaseMapper<T> mapper) {
		return saveCommon(mapper, null);
	}

	protected interface IUpdateObj<V> {
		public void doUpdate(V po, boolean isInsert);
	}

}
