use std::{
  collections::HashSet,
  sync::{Arc, RwLock},
};

use rayon::prelude::*;

/// 快速去重
pub trait DeduplicatableFast<T> {
  fn hash_dedup(&self) -> Vec<T>;
  fn hash_dedup_sync(self) -> Vec<T>;
}
impl<T, A> DeduplicatableFast<T> for A
where
  A: AsRef<[T]>,
  T: Eq + Clone + std::hash::Hash + Send + Sync,
{
  /// 并行
  fn hash_dedup(&self) -> Vec<T> {
    hash_dedup(self.as_ref().to_vec())
  }
  /// 加锁并行
  fn hash_dedup_sync(self) -> Vec<T> {
    hash_dedup_sync(self.as_ref().to_vec())
  }
}
/// # 去重
/// 优点：
/// 并行化处理：利用 Rayon 并行迭代器可以充分利用多核处理器的并行性能，加快去重操作的速度。
/// 快速查找：HashSet 提供了快速的查找功能，可以快速判断元素是否已经存在于集合中，避免了重复元素的插入。
/// 一次迭代完成：该方法可以在一次迭代中完成去重操作，避免了额外的内存分配和元素复制。
///
/// 不足：
/// 内存占用：HashSet 在并行化去重操作中可能会占用较多的内存，尤其是对于大规模数据集。
/// 竞争情况：虽然使用了并行迭代器和 HashSet 的并行插入方法，但仍然可能存在锁竞争的情况，影响并行性能。
/// 无序性：HashSet 是无序的数据结构，可能会改变原始数据的顺序。
///
/// 时间复杂度：
/// 插入和查找元素的时间复杂度为 O(1)，因此整体时间复杂度取决于向量中元素的数量，为 O(n)，其中 n 是向量中元素的个数。
///
/// #Example
/// ```rust
///fn test() -> Result<()> {
///   let x = vec![1, 1, 1, 1, 3, 4, 5, 6, 88, 77, 7, 7, 7, 3, 7, 1, 81, 91];
///   let x = hash_dedup(x);
///   println!("dedup [{:?}]  ]", x);
///   Ok(())
/// }
/// ```
pub fn hash_dedup<T>(data: Vec<T>) -> Vec<T>
where
  T: std::hash::Hash + Eq + Clone + Sync + Send,
{
  data
    .par_iter()
    .cloned()
    .collect::<HashSet<_>>()
    .into_iter()
    .collect()
}

/// # 去重
/// 优点：
/// 并行化处理：利用 Rayon 并行迭代器可以充分利用多核处理器的并行性能，加快去重操作的速度。
/// 快速查找：HashSet 提供了快速的查找功能，可以快速判断元素是否已经存在于集合中，避免了重复元素的插入。
/// 一次迭代完成：该方法可以在一次迭代中完成去重操作，避免了额外的内存分配和元素复制。
///
/// 不足：
/// 内存占用：HashSet 在并行化去重操作中可能会占用较多的内存，尤其是对于大规模数据集。
/// 竞争情况：虽然使用了并行迭代器和 HashSet 的并行插入方法，但仍然可能存在锁竞争的情况，影响并行性能。
/// 无序性：HashSet 是无序的数据结构，可能会改变原始数据的顺序。
///
/// 时间复杂度：
/// 插入和查找元素的时间复杂度为 O(1)，因此整体时间复杂度取决于向量中元素的数量，为 O(n)，其中 n 是向量中元素的个数。
///
/// #Example
/// ```rust
///fn test() -> Result<()> {
///   let x = vec![1, 1, 1, 1, 3, 4, 5, 6, 88, 77, 7, 7, 7, 3, 7, 1, 81, 91];
///   let x = hash_dedup_sync(x);
///   println!("dedup [{:?}]  ]", x);
///   Ok(())
/// }
/// ```
pub fn hash_dedup_sync<T>(data: Vec<T>) -> Vec<T>
where
  T: std::hash::Hash + Eq + Clone + Send + Sync,
{
  let set = Arc::new(RwLock::new(HashSet::new()));

  let deduplicated: Vec<_> = data
    .into_par_iter()
    .filter_map(|item| {
      let mut lock = set.write().unwrap();
      if lock.insert(item.clone()) {
        Some(item)
      } else {
        None
      }
    })
    .collect();

  deduplicated
}
