package com.iamberry.wechat.utils;

import com.iamberry.wechat.core.entity.page.PagedResult;
import org.springframework.web.servlet.ModelAndView;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 解决rst列表参数拼接问题
 */
public class StitchAttrUtil {

    public static StitchAttrUtil getSa(){
        return new StitchAttrUtil();
    }

    private StitchAttrUtil(){
        propertySet = new HashSet<String>(Arrays.asList(noProperty));
    };

    /**
     * 组装参数时，会过滤以下参数
     * 推荐使用：addDatePro()，添加过滤
     */
    // TODO: 2018/8/28  time 的转换调整，支持一个类中有有多种time的格式，因此注释掉初始化的time的Set，只能使用addDatePro()
//    private final  String timeDate[] = {};

    /**
     * 控制时间参数格式
     * 推荐使用：addDatePro()，添加过滤
     */
    private final String noProperty[] = {
            "serialVersionUID",
            "page"
    };


    private Set<String> propertySet;
    private Map<String,SimpleDateFormat> timeMap = new HashMap<String,SimpleDateFormat>();

    /**
     * 组装ModelAndView
     * @param object
     * @param modelAndView
     * @param url
     * @param pagedResult
     * @throws IllegalAccessException
     */
    public void setModelAndView(Object object, ModelAndView modelAndView, String url, PagedResult<?> pagedResult) {
        StringBuilder sb = new StringBuilder(url);

        if(pagedResult.getTotal() != 0) {
            pagedResult.setPages((int) Math.ceil((double)pagedResult.getTotal()/pagedResult.getPageSize()));
        }

        sb.append("?pageSize=" + pagedResult.getPageSize());
        sb.append("&totalNum=" + pagedResult.getTotal() );
        this.setUrlByObj(sb,object);
        sb.append("&&pageNO=");

        Map<String, Object> map = this.getObjToMap(object);
        modelAndView.addAllObjects(map);

        modelAndView.addObject("page", pagedResult);
        modelAndView.addObject("url", sb.toString());

        modelAndView.addObject("pageNO", pagedResult.getPageNO());
        modelAndView.addObject("pageSize", pagedResult.getPages());
        return;
    }

    /**
     * 将obj 转为map，
     * 属性值为null的不会 put 到 Map 中
     * 属性名称在  noProperty 数组中的属性不会 put 到 Map 中
     * @param object
     * @return
     * @throws IllegalAccessException
     */
    public Map<String, Object> getObjToMap(Object object) {
        Map<String, Object> map = new HashMap<>();
        Class<?> clazz = object.getClass();
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            String fieldName = field.getName();
            Object value = null;
            try {
                value = field.get(object);
            }catch (IllegalAccessException e){
            }
            if (value != null && !propertySet.contains(fieldName)) {
                map.put(fieldName, value);
            }
        }
        return map;
    }

    /**
     * 拼接url
     * @param sb
     * @param object
     * @throws IllegalAccessException
     */
    public void setUrlByObj(StringBuilder sb,Object object){
        Class<?> clazz = object.getClass();
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            String fieldName = field.getName();
            Object value = null;
            try {
                value = field.get(object);
            }catch (IllegalAccessException e){
            }
            if (value != null && !propertySet.contains(fieldName)) {
                /* 遍历map,将时间格式进行转换 */
                for (Map.Entry<String, SimpleDateFormat> entry : timeMap.entrySet()) {
                    if(entry.getKey().equals(fieldName)){
                        value = entry.getValue().format(value);
                    }
                }
                sb.append("&"+fieldName+ "=" + value.toString());
            }
        }
    }

    /**
     * 判断是否还有下一页
     * @param pagedResult
     * @return
     */
    public boolean getLastPage( PagedResult<?> pagedResult){
        /* 当前页 >= 总页面数目 */
        if(pagedResult.getPageNO() >=  pagedResult.getPages()){
            return false;
        }else{
            return true;
        }
    }

    /**
     * 添加组装时被过滤的属性名称
     * @param pros
     */
    public StitchAttrUtil addNoPro(String...pros){
        for(String pro : pros){
            if(pro != null && !"".equals(pro))
                propertySet.add(pro);
        }
        return this;
    }

    /**
     * 添加时间参数格式
     * @param fom   //"yyyy-MM-dd HH:mm:ss"
     * @param pros
     */
    public StitchAttrUtil addDatePro(String fom, String...pros){
        SimpleDateFormat sdf = new SimpleDateFormat(fom);
        for(String pro : pros){
            if(pro != null && !"".equals(pro)){
                timeMap.put(pro,sdf);
            }
        }
        return this;
    }

    /**
     * 给page赋值
     * @param pagedResult
     */
    public static void setPage(PagedResult<?> pagedResult){
        if(pagedResult.getTotal() != 0) {
            pagedResult.setPages((int) Math.ceil((double)pagedResult.getTotal()/pagedResult.getPageSize()));
        }
    }

}
