package com.yanzuoguang.util.helper;

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

/**
 * 映射处理
 *
 * @author 颜佐光
 */
public class MapHelper {

    /**
     * 将一个对象列表转换为HashMap
     *
     * @param list 需要转换的列表
     * @param <T>  泛型
     * @return 泛型处理
     */
    public static <T extends MapKey<T>> Map<String, T> getMap(List<T> list) {
        return getMap(list, (item) -> item.getKey(item));
    }

    /**
     * 将一个对象列表转换为HashMap
     *
     * @param list  需要转换的列表
     * @param proxy 获取主键的函数
     * @param <T>   泛型
     * @return 泛型处理
     */
    public static <T extends Object> Map<String, T> getMap(List<T> list, MapKey<T> proxy) {
        if (list == null) {
            return new HashMap<>(0);
        }
        Map<String, T> map = new HashMap<>(list.size());
        for (T item : list) {
            String key = proxy.getKey(item);
            map.put(key, item);
        }
        return map;
    }

    /**
     * 将一个对象列表转换为HashMap
     *
     * @param list  需要转换的列表
     * @param proxy 获取主键的函数
     * @param <T>   类型
     * @param <M>   关键字类型
     * @return 映射结果
     */
    public static <T, M> Map<M, T> getMapType(List<T> list, MapKeyType<T, M> proxy) {
        if (list == null) {
            return new HashMap<>(0);
        }
        Map<M, T> map = new HashMap<>(list.size());
        for (T item : list) {
            M key = proxy.getKey(item);
            map.put(key, item);
        }
        return map;
    }

    /**
     * 将一个对象列表转换为HashMap
     *
     * @param list 需要转换的列表
     * @param <T>  泛型
     * @return 泛型处理
     */
    public static <T extends MapKey<T>> List<String> getKeys(List<T> list) {
        if (list == null) {
            return new ArrayList<>();
        }
        List<String> to = new ArrayList<>(list.size());
        for (T item : list) {
            String key = item.getKey(item);
            if (!to.contains(key)) {
                to.add(key);
            }
        }
        return to;
    }

    /**
     * 将一个对象列表转换为HashMap
     *
     * @param list  需要转换的列表
     * @param proxy 获取主键的函数
     * @param <T>   泛型
     * @return 泛型处理
     */
    public static <T extends Object> List<String> getKeys(List<T> list, MapKey<T> proxy) {
        List<String> to = new ArrayList<>();
        if (list != null) {
            for (T item : list) {
                String key = proxy.getKey(item);
                if (!to.contains(key)) {
                    to.add(key);
                }
            }
        }
        return to;
    }

    /**
     * 将建添加到子数组中
     *
     * @param mapList 列表
     * @param key     关键字
     * @param item    对象
     * @param <T>     关键字类型
     * @param <M>     关键字对象
     * @return 最终结果
     */
    public static <T, M> List<M> addMapList(Map<T, List<M>> mapList, T key, M item) {
        if (!mapList.containsKey(key)) {
            mapList.put(key, new ArrayList<>());
        }
        List<M> ret = mapList.get(key);
        ret.add(item);
        return ret;
    }

    /**
     * 一个获取对象关键字的处理函数
     *
     * @param <T> 泛型
     */
    public interface MapKey<T> extends MapKeyType<T, String> {
    }

    /**
     * 一个获取对象关键字的处理函数
     *
     * @param <T> 泛型
     * @param <M> 泛型
     */
    public interface MapKeyType<T, M> {
        /**
         * 获取关键字
         *
         * @param from 来源数据
         * @return 关键字
         */
        M getKey(T from);
    }
}