package com.prolog.cs.biz.inbound.service.impl;

import com.prolog.cs.biz.inbound.constant.VaildateConstant;
import com.prolog.cs.biz.inbound.constant.ValidatorGroup.validAdd;
import com.prolog.cs.biz.inbound.constant.ValidatorGroup.validEdit;
import com.prolog.cs.biz.inbound.dto.PageParam;
import com.prolog.framework.authority.core.dto.UserDTO;
import com.prolog.framework.bz.core.model.BaseModel;
import com.prolog.framework.bz.core.model.ModelUtils;
import com.prolog.framework.bz.core.util.ObjectUtils;
import com.prolog.framework.core.exception.ParameterException;
import com.prolog.framework.core.pojo.Page;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.dao.util.PageUtils;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.function.Function;

/**
 * 业务实现类基类
 * 
 * @author Xiong
 *
 * @param <T>
 */
public class BaseServiceImpl<T extends BaseModel> {

	/**
	 * 添加基础字段
	 * 
	 * @param baseModel 数据model
	 * @param userDTO   用户数据
	 */
	public void setBaseSysField(T baseModel, UserDTO userDTO) {
		setBaseSysField(baseModel, false, userDTO);
	}

	/**
	 * 添加基础字段
	 * 
	 * @param baseModel 数据model
	 * @param editFlag  编辑标志
	 * @param userDTO   用户数据
	 */
	public void setBaseSysField(T baseModel, boolean editFlag, UserDTO userDTO) {
		setBaseSysField(baseModel, editFlag, userDTO, new Date());
	}

	/**
	 * 添加基础字段
	 * 
	 * @param baseModel 数据model
	 * @param editFlag  编辑标志
	 * @param userDTO   用户数据
	 * @param date      时间
	 */
	public void setBaseSysField(T baseModel, boolean editFlag, UserDTO userDTO, Date date) {
		if (editFlag)
			ModelUtils.setBaseInfo(baseModel, ModelUtils.OpType.UPDATE, userDTO, date);
		else
			ModelUtils.setBaseInfo(baseModel, ModelUtils.OpType.INSERT, userDTO, date);

	}

	/**
	 * 构建前端分页数据
	 * 
	 * @param <S>
	 * @param src
	 * @param func
	 * @return
	 */
	public <S> Page<S> buildPage(Page<T> src, Function<T, S> func) {

		if (ObjectUtils.isNull(src))
			return null;

		Page<S> page = new Page<S>();
		page.setStartRow(src.getStartRow());
		page.setEndRow(src.getEndRow());
		page.setPageCount(src.getPageCount());
		page.setPageNum(src.getPageNum());
		page.setPageSize(src.getPageSize());
		page.setTotalCount(src.getTotalCount());
		List<T> list = src.getList();

		if (list != null && list.size() > 0) {
			List<S> list2 = new ArrayList<S>();
			list.stream().forEach(x -> {
				S s = func.apply(x);
				list2.add(s);
			});
			page.setList(list2);
		}

		return page;
	}

	/**
	 * 构建分页查询参数
	 * 
	 * @param pp           分页参数类
	 * @param defaultOrder 是否默认根据更新时间排序
	 * @param orders       排序的数组 类似 [xx#desc,xx#asc]
	 * @param cls          待查询的对象class
	 * @return
	 */
	public Criteria buildPageParam(PageParam pp, boolean defaultOrder, String[] orders, Class<T> cls) {
		Criteria criteria = new Criteria(cls);
		if (defaultOrder)
			criteria.setOrder(Order.newInstance().desc("gmtModified"));
		return criteria;
	}

	public Criteria initCondition(boolean defaultOrder, String[] orders, Class<T> cls) {
		Criteria criteria = new Criteria(cls);
		Order order = Order.newInstance();
		if (defaultOrder) {
			order.desc("gmtModified");
		}
		if (ObjectUtils.isNotNull(orders)) {
			for (String string : orders) {
				String[] split = string.split("#");
				if (split[1].trim().toLowerCase().equals("desc")) {
					order.desc(split[0]);
				}
				if (split[1].trim().toLowerCase().equals("asc")) {
					order.asc(split[0]);
				}
			}
		}
		criteria.setOrder(order);
		return criteria;
	}

	public void startPage(PageParam pp) {
		if (ObjectUtils.isNull(pp))
			pp = new PageParam();
		Integer pageNum = pp.getPageNum();
		Integer pageSize = pp.getPageSize();
		if (ObjectUtils.isNull(pageNum,false))
			pageNum = PageParam.DEFAULT_PAGE_NUM;
		if (ObjectUtils.isNull(pageSize,false))
			pageSize = PageParam.DEFAULT_PAGE_SIZE;
		PageUtils.startPage(pageNum, pageSize);
	}

	/**
	 * 校验数据
	 * 
	 * @param r         需要校验的对象
	 * @param editFlag  编辑标识
	 * @param userDTO   用户信息
	 * @param row       行数
	 * @param validator 校验对象
	 * @param msg       操作提示信息
	 */
	public <R> void vaildateModel(R r, boolean editFlag, UserDTO userDTO, int row, Validator validator, String msg) {
		// 校验数据
		Set<ConstraintViolation<R>> validate = null;
		if (!editFlag) {
			// 添加校验
			validate = validator.validate(r, validAdd.class);
		} else {
			validate = validator.validate(r, validEdit.class);
		}
		if (validate != null && !validate.isEmpty()) {
			StringBuilder sb = new StringBuilder();
			if (row > 0)
				sb.append(String.format(VaildateConstant.ERROR_ROW_FORMAT2, msg, row));
			validate.forEach((validation) -> {
				String errorMsg = validation.getMessage();
				String propertyName = validation.getPropertyPath().toString();
				sb.append(String.format(VaildateConstant.ERROR_FIELD_FORMAT, propertyName))
						.append(String.format(VaildateConstant.ERROR_MSG_FORMAT, errorMsg));
			});
			throw new ParameterException(sb.toString());
		}
	}

}
