use std::{collections::HashSet, hash::Hash};
use std::collections::HashMap;

/// Collection-related utility classes, such as for intersections, unions, reversal, element removal, etc.
pub struct CollectionUtil;

/// vec常规操作
impl CollectionUtil {

    pub fn is_empty<T>(vec: &[T]) -> bool {
        vec.is_empty()
    }

    pub fn is_not_empty<T>(vec: &[T]) -> bool {
        !vec.is_empty()
    }

    /// 获取vec的第一个元素，不移除
    pub fn first<T>(vec: &[T]) -> Option<&T> {
        vec.get(0)
    }

    pub fn second<T>(vec: &[T]) -> Option<&T> {
        vec.get(1)
    }

    pub fn third<T>(vec: &[T]) -> Option<&T> {
        vec.get(2)
    }

    /// 移除并获取vec的第一个元素
    pub fn remove_first<T>(vec: &mut Vec<T>) -> Option<T> {
        if vec.len() > 0 { Some(vec.remove(0)) } else { None }
    }

    /// 获取vec的最后一个元素，不移除
    pub fn last<T>(vec: &[T]) -> Option<&T> {
        vec.last()
    }
    
    /// 获取vec的最后一个元素，移除
    pub fn pop<T>(vec: &mut Vec<T>) -> Option<T> {
        vec.pop()
    }

    /// 反转向量中的元素顺序
    pub fn reverse<T>(vec: &mut [T]) {
        vec.reverse()
    }

    /// 移除重复的元素
    pub fn distinct<T: Eq + Hash + Clone>(vec: &[T]) -> Vec<T> {
        let mut hash_set = HashSet::new();
        for item in vec.iter() {
            hash_set.insert(item.clone());
        }
        hash_set.into_iter().collect()
    }

    /// 找到切片中的最大元素
    pub fn max<T: Ord>(vec: &[T]) -> Option<&T>{
        vec.iter().max()
    }

    /// 找到切片中的最小元素
    pub fn min<T: Ord>(vec: &[T]) -> Option<&T>{
        vec.iter().min()
    }

    /// 将两个切片连接成一个新的向量
    ///
    /// 该函数接收两个相同类型的切片，并将它们的元素按顺序复制到一个新的向量中。
    /// 使用预分配容量的方式来提高内存分配效率。
    ///
    /// # 参数
    /// * `vec1` - 第一个切片引用，其元素将出现在结果向量的前面部分
    /// * `vec2` - 第二个切片引用，其元素将出现在结果向量的后面部分
    ///
    /// # 返回值
    /// 返回一个包含两个输入切片所有元素的新向量，元素顺序保持不变
    ///
    /// # 泛型约束
    /// * `T: Copy` - 要求元素类型实现Copy trait，以便能够复制元素

    pub fn concat_slices<T: Copy>(vec1: &[T], vec2: &[T]) -> Vec<T> {
        let mut result = Vec::with_capacity(vec1.len() + vec2.len()); // 预分配容量，提高效率
        result.extend(vec1.iter().copied());
        result.extend(vec2.iter().copied());
        result
    }

    /// 对切片进行排序
    ///
    /// 该函数使用标准库的排序算法对给定切片进行原地排序
    ///
    /// # 参数
    ///
    /// * `vec` - 需要排序的可变切片引用
    ///
    /// # 泛型约束
    ///
    /// * `T` - 必须实现 `Ord` trait，即支持全序比较
    pub fn sort<T>(vec: &mut [T]) where T: Ord {
        vec.sort()
    }

    /// 将切片中的元素映射到HashMap中，使用指定的键提取函数生成键
    /// 
    /// # 参数
    /// * `vec` - 包含值的切片引用
    /// * `key_fn` - 用于从值中提取键的函数
    /// 
    /// # 返回值
    /// 返回一个HashMap，其中键是通过key_fn函数从值中提取的，值是对原切片中元素的引用
    /// 
    /// # 泛型参数
    /// * `K` - HashMap的键类型，必须实现Eq和Hash trait
    /// * `V` - 切片中值的类型
    /// * `Accessor` - 键提取函数的类型，必须是一个接受&V并返回K的函数
    pub fn mapping<K, V, Accessor>(vec: &[V], key_fn: Accessor) -> HashMap<K, &V>
    where
        K: Eq + Hash,
        Accessor: Fn(&V) -> K
    {
        // 创建一个新的HashMap来存储映射结果
        let mut map = HashMap::new();
        // 遍历切片中的每个元素，将键值对插入到HashMap中
        for item in vec.iter() {
            map.insert(key_fn(item), item);
        }
        map
    }


    /// 按指定规则对切片中的元素进行分组
    /// 
    /// 该函数接收一个切片和一个键生成函数，将切片中的元素按照键生成函数的结果进行分组，
    /// 返回一个 HashMap，其中键为分组依据，值为属于该分组的元素引用组成的向量。
    /// 
    /// # 参数
    /// * `vec` - 需要分组的元素切片
    /// * `key_fn` - 键生成函数，用于为每个元素生成分组依据
    /// 
    /// # 返回值
    /// 返回一个 HashMap，键类型为 K，值类型为 Vec<&V>，包含所有分组结果
    /// 
    /// # 泛型参数
    /// * `K` - 分组键的类型，必须实现 Eq 和 Hash trait
    /// * `V` - 切片中元素的类型
    /// * `Accessor` - 键生成函数的类型，必须实现 Fn(&V) -> K
    pub fn group_by<K, V, Accessor>(vec: &[V], key_fn: Accessor) -> HashMap<K, Vec<&V>>
    where
        K: Eq + Hash,
        Accessor: Fn(&V) -> K
    {
        let mut map = HashMap::new();
        // 遍历切片中的每个元素，按 key_fn 生成的键进行分组
        for item in vec.iter() {
            // 为当前元素生成 key
            let key = key_fn(&item);
            // 将元素插入对应 key 的 Vec 中（不存在则自动创建）
            map.entry(key).or_insert_with(Vec::new).push(item);
        }
        map
    }


    /// 计算交集：两个集合中都存在的元素
    pub fn intersection<T>(vec1: Vec<T>, vec2: Vec<T>) -> Vec<T>
    where T: Eq + Hash + Clone {
        // 转换为HashSet
        let set1: HashSet<T> = vec1.into_iter().collect();
        let set2: HashSet<T> = vec2.into_iter().collect();
        // 计算交集：两个集合中都存在的元素
        let result: Vec<T> = set1.intersection(&set2).cloned().collect();
        result
    }

    /// 计算并集：两个集合中所有不重复的元素
    pub fn union<T>(vec1: Vec<T>, vec2: Vec<T>) -> Vec<T>
    where T: Eq + Hash + Clone {
        let set1: HashSet<T> = vec1.into_iter().collect();
        let set2: HashSet<T> = vec2.into_iter().collect();
        // 计算并集：两个集合中所有不重复的元素
        let result: Vec<_> = set1.union(&set2).cloned().collect();
        result
    }

    /// 计算差集：set1中有而set2中没有的元素
    pub fn difference<T>(vec1: Vec<T>, vec2: Vec<T>) -> Vec<T>
    where T: Eq + Hash + Clone {
        let set1: HashSet<T> = vec1.into_iter().collect();
        let set2: HashSet<T> = vec2.into_iter().collect();
        // 计算差集：set1中有而set2中没有的元素
        let result: Vec<_> = set1.difference(&set2).cloned().collect();
        result
    }

    /// 计算对称差集：只在其中一个集合中出现的元素
    pub fn symmetric_difference<T>(vec1: Vec<T>, vec2: Vec<T>) -> Vec<T>
    where T: Eq + Hash + Clone {
        let set1: HashSet<T> = vec1.into_iter().collect();
        let set2: HashSet<T> = vec2.into_iter().collect();
        // 计算对称差集：只在其中一个集合中出现的元素
        let result: Vec<_> = set1.symmetric_difference(&set2).cloned().collect();
        result
    }


}


#[cfg(test)]
mod tests {
    use std::collections::HashMap;


    #[test]
    fn test_remove_first() {
        let _map = HashMap::<i32, i32>::new();
    }
}

