package com.yanzuoguang.util.vo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据库操作对象
 *
 * @param <T>
 * @author 颜佐光
 */
public class DataDaoVo<T> {
    private final List<T> creates = new ArrayList<>();
    private final List<T> updates = new ArrayList<>();
    private final List<T> removes = new ArrayList<>();
    private final Map<String, T> mapNow = new HashMap<>();

    /**
     * 合并数据
     *
     * @param data 当前数据对象
     */
    public void merger(DataDaoVo<T> data) {
        this.creates.addAll(data.creates);
        this.updates.addAll(data.updates);
        this.removes.addAll(data.removes);
        this.mapNow.putAll(data.mapNow);
    }

    /**
     * 将历史数据映射为HashMap
     *
     * @param hisList 历史数据
     * @param keyFunc 获取主键函数
     * @return 映射值
     */
    private Map<String, T> getMapHistory(List<T> hisList, DataDaoKey<T> keyFunc) {
        // 定义缓存集合
        Map<String, T> mapHistory = new HashMap<>(10);
        // 历史数据处理
        if (hisList != null) {
            for (T his : hisList) {
                if (his == null) {
                    continue;
                }
                String key = keyFunc.getKey(his);
                mapHistory.put(key, his);
            }
        }
        return mapHistory;
    }

    /**
     * 获取结果
     *
     * @param hisList    历史数据
     * @param mapHistory 历史数据映射
     * @param nowList    当前数据
     * @param keyFunc    获取主键函数
     */
    private void addResult(List<T> hisList, Map<String, T> mapHistory, List<T> nowList, DataDaoKey<T> keyFunc) {
        // 需要删除的集合
        List<T> historyRemove = new ArrayList<>(hisList);
        // 返回集
        if (nowList != null) {
            for (T now : nowList) {
                if (now == null) {
                    continue;
                }
                String key = keyFunc.getKey(now);
                T his = mapHistory.get(key);
                if (his == null) {
                    this.creates.add(now);
                    this.mapNow.put(key, now);
                } else {
                    historyRemove.remove(his);
                    boolean isChange = keyFunc.set(his, now);
                    if (isChange) {
                        this.updates.add(his);
                    }
                    this.mapNow.put(key, his);
                }
            }
        }
        this.removes.addAll(historyRemove);
    }


    /**
     * 初始话对象
     *
     * @param hisList 历史列表
     * @param nowList 当前列表
     * @param keyFunc 函数
     */
    public void add(List<T> hisList, List<T> nowList, DataDaoKey<T> keyFunc) {
        Map<String, T> mapHistory = getMapHistory(hisList, keyFunc);
        addResult(hisList, mapHistory, nowList, keyFunc);
    }


    /**
     * 初始话对象
     *
     * @param hisList 历史列表
     * @param nowList 当前列表
     * @param keyFunc 处理函数
     */
    public <M> void add(List<T> hisList, List<M> nowList, DataDaoKeyConvert<T, M> keyFunc) {
        Map<String, T> mapHistory = getMapHistory(hisList, keyFunc);
        List<T> nowListTo = new ArrayList<>(10);
        if (nowList != null) {
            for (M m : nowList) {
                T t = keyFunc.convert(mapHistory, m);
                nowListTo.add(t);
            }
        }
        addResult(hisList, mapHistory, nowListTo, keyFunc);
    }

    /**
     * 初始话对象
     *
     * @param hisList 历史列表
     * @param nowList 当前列表
     * @param keyFunc 处理函数
     */
    public static <T> DataDaoVo<T> init(List<T> hisList, List<T> nowList, DataDaoKey<T> keyFunc) {
        DataDaoVo<T> res = new DataDaoVo<T>();
        res.add(hisList, nowList, keyFunc);
        return res;
    }


    /**
     * 初始话对象
     *
     * @param hisList 历史列表
     * @param nowList 当前列表
     * @param keyFunc 处理函数
     */
    public static <T, M> DataDaoVo<T> init(List<T> hisList, List<M> nowList, DataDaoKeyConvert<T, M> keyFunc) {
        DataDaoVo<T> res = new DataDaoVo<T>();
        res.add(hisList, nowList, keyFunc);
        return res;
    }

    /**
     * 需要创建的对象
     *
     * @return
     */
    public List<T> getCreates() {
        return creates;
    }

    /**
     * 需要修改的对象
     *
     * @return
     */
    public List<T> getUpdates() {
        return updates;
    }

    /**
     * 需要删除的对象
     *
     * @return
     */
    public List<T> getRemoves() {
        return removes;
    }

    /**
     * 所有需要修改和更新的对象
     *
     * @return
     */
    public Map<String, T> getMapNow() {
        return mapNow;
    }
}