use crate::game::component::{self, *};
use rand::distributions::weighted;
use rocksdb::{ColumnFamilyDescriptor, DBCommon, IteratorMode, Options, SingleThreaded, DB};
use std::collections::HashSet;
use std::marker::PhantomData;
use num::traits::cast::ToPrimitive;
use rayon::iter::{IntoParallelRefIterator, IntoParallelIterator, IndexedParallelIterator, ParallelIterator, IntoParallelRefMutIterator};
use std::sync::{Arc, atomic::{AtomicUsize, Ordering}};
use super::*;

pub struct PaEmdCluster<T> {
    kriso2bucket_street: Vec<Vec<usize>>,
    bucket_size_street: Vec<usize>,
    abstr_configs: Vec<AbstractAlgorithmStreet>,
    _marker: PhantomData<T>
}

impl<T> PaEmdCluster<T>
    where T: Singleton + Hand + WaughTrait + ShowdownRanker + 'static,
{

    pub fn new(alg_configs: &[AbstractAlgorithmStreet]) -> Self{
        assert_eq!(alg_configs.len(), T::NUM_STREET as usize);

        fn started_paemd_recognition(alg_configs: &[AbstractAlgorithmStreet]) -> Option<usize> {
            // 变量来记录迭代状态
            let mut in_isomorphism = true;
            let mut paemd_started_street = 0;
        
            // 检查前几个元素是否为连续的 Isomorphism
            for (street, config) in alg_configs.iter().enumerate() {
                match config {
                    AbstractAlgorithmStreet::Isomorphism { .. } => {
                        if !in_isomorphism {
                            // 如果状态转换，但发现之前已经结束了 Isomorphism 部分，返回 None
                            return None;
                        }
                    }
                    AbstractAlgorithmStreet::PaEmd { .. } => {
                        // 转换到 PaEmd 部分
                        if in_isomorphism {
                            paemd_started_street = street;
                        }
                        in_isomorphism = false;
                    }
                    _ => {
                        // 如果出现其他变体，返回 None
                        return None;
                    }
                }
            }
        
            // 检查最后几个元素是否全为 PaEmd
            if in_isomorphism {
                // 如果迭代结束后仍在 Isomorphism 部分，返回 false
                return None;
            }
        
            Some(paemd_started_street)
        }

        let mut kriso2bucket_street = vec![];
        let mut bucket_size_street= vec![];

        let paemd_started_street = started_paemd_recognition(alg_configs).unwrap();

        let mut next_assign: Option<Vec<usize>> = None;
        let mut next_ordered_centroids: Option<Vec<Vec<usize>>> = None;
        let mut next_distances: Option<Vec<Vec<f64>>> = None;
        // paemd part
        for street in (paemd_started_street..alg_configs.len()).rev(){
            if let AbstractAlgorithmStreet::PaEmd {centroid_size, train_iteration} = alg_configs[street] {
                
                let nriso_assign = if street + 1 == alg_configs.len() {
                    let (nriso_assign, assign_result, ordered_centorids_result, distances_result) = Self::terminal_street_cluster(centroid_size, train_iteration);
                    (next_assign, next_ordered_centroids, next_distances) = (Some(assign_result), Some(ordered_centorids_result), Some(distances_result));
                    nriso_assign
                }
                else {
                    let (nriso_assign, assign_result, ordered_centorids_result, distances_result) = Self::nonterminal_street_cluster(street, next_assign.as_ref().unwrap(), next_ordered_centroids.unwrap(), next_distances.unwrap(), centroid_size, train_iteration);
                    (next_assign, next_ordered_centroids, next_distances) = (Some(assign_result), Some(ordered_centorids_result), Some(distances_result));
                    nriso_assign
                };
                
                kriso2bucket_street.insert(0, nriso_assign);
                bucket_size_street.insert(0, centroid_size);
            }
            else {
                panic!("不能到这里");
            }
        }

        for street in (0..paemd_started_street).rev() {
            if let AbstractAlgorithmStreet::Isomorphism {recall_from} = alg_configs[street] {
                let (kriso_assign, bucket_size) = load_isomorphism_abstr::<T>(street, recall_from);
                kriso2bucket_street.insert(0, kriso_assign);
                bucket_size_street.insert(0, bucket_size);
            }
            else {
                panic!("不能到这里");
            }
        }

        Self {
            kriso2bucket_street,
            bucket_size_street,
            abstr_configs: alg_configs.iter().cloned().collect::<Vec<_>>(),
            _marker: PhantomData,    
        }

    }

    pub fn terminal_street_cluster(centroids_size:usize, max_iter:usize) -> (Vec<usize>, Vec<usize>, Vec<Vec<usize>>, Vec<Vec<f64>>) {
        let street = T::NUM_STREET as usize - 1;
        // 1.读数据
        // nriso2distid, nrid2dist, nrid2equity
        let (nriso2distid, distsize) = Self::load_terminal_wdistid_with_nriso();
        let nrid2dist = Self::load_terminal_wdist_with_id();
        assert_eq!(distsize, nrid2dist.len());
        let nrid2equity :Vec<_> = nrid2dist
            .par_iter()
            .map(|dist| {
                dist[1] + 2 * dist[2]
            })
            .collect();
        {
            let unique: HashSet<_> = nrid2equity.iter().cloned().collect();
            assert!(centroids_size <= unique.len());
        }
        let nrid2equity :Vec<_> = nrid2dist
            .into_par_iter()
            .map(|dist| {
                (1.0 * dist[1].to_f64().unwrap() + 2.0 * dist[2].to_f64().unwrap())/dist.iter().sum::<i64>().to_f64().unwrap()
            })
            .collect();
        

        // 2.找weight
        let nrid2weight: Arc<Vec<AtomicUsize>> = Arc::new((0..nrid2equity.len()).into_par_iter().map(|_| AtomicUsize::new(0)).collect());
        nriso2distid
            .par_iter()
            .enumerate()
            .for_each( |(nriso, &distid)| {
                let recall_from=street;
                let adder = T::instance().hand_index_volumn(nriso, street, recall_from);
                nrid2weight[distid].fetch_add(adder, Ordering::Relaxed);
            });
        let nrid2weight: Vec<usize> = nrid2weight
            .par_iter()
            .map(|x| x.load(Ordering::Relaxed))
            .collect();
        // let checksum = nrid2weight.par_iter().sum::<usize>();

        // 3.写两个函数
        let average_closure = {
            move |pnt_idx: &[usize], pnts: &[f64], w8s: &[usize]| -> f64{
                let mut sum = 0.0;
                let mut weight_sum = 0;
        
                for &idx in pnt_idx {
                    sum += pnts[idx] * w8s[idx].to_f64().unwrap();  // 累加加权值
                    weight_sum += w8s[idx];  // 累加权重
                }
        
                sum / weight_sum.to_f64().unwrap()  // 计算加权平均值
            }
        };
        let distance_batch_closure = {
            move |pntidcs: &[usize], pnts: &[f64], ctrd: &f64| -> Vec<f64> {

                pntidcs
                    .par_iter()
                    .map(|&pntidx| {
                        (pnts[pntidx] - ctrd).abs()
                    })
                    .collect::<Vec<f64>>()
            }
        };

        // 4.kmeanspp
        let kmeanspp: WeightedKmeansPP<f64, f64> = WeightedKmeansPP::<f64, f64> {
            points: nrid2equity,
            weights: nrid2weight,
            average_fn: Box::new(average_closure),
            distance_batch_fn: Box::new(distance_batch_closure),
        };
        let (dist_assign, centroid_pointidcs, centroids) = kmeanspp.kmeanspp_process(centroids_size, max_iter, false);

        // 5. dist_assign -> nriso
        let nriso_size = T::instance().hand_isomorphism_size_street(street, street);
        let nriso_assign = (0..nriso_size)
            .into_par_iter()
            .map(|nriso| {
                let nrid = nriso2distid[nriso];
                let bucket = dist_assign[nrid];
                bucket
            })
            .collect::<Vec<_>>();

        // 6. distance table
        // 构建
        let mut distances: Vec<Vec<f64>> ={
            let centroids_weight = centroid_pointidcs
                .par_iter()
                .map(|ctrd_pnts| {
                    let total_weight = ctrd_pnts
                        .iter()
                        .map(|&distid| {
                            kmeanspp.weights[distid]
                        })
                        .sum::<usize>();
                    total_weight
                })
                .collect::<Vec<_>>();
            let checksum = centroids_weight.iter().sum::<usize>();

            let mut weighted_distance = vec![vec![0_f64; centroids_size]; centroids_size];
            weighted_distance
                .par_iter_mut()
                .enumerate()
                .for_each(|(ctrda_idx, disvec)| {
                    disvec
                        .iter_mut()
                        .enumerate()
                        .for_each(|(ctrdb_idx, w8ed_dis)| {
                            let batch_distance = (kmeanspp.distance_batch_fn)(centroid_pointidcs[ctrda_idx].as_ref(), kmeanspp.points.as_ref(), &centroids[ctrdb_idx]);
                            let total_distance = centroid_pointidcs[ctrda_idx]
                                .iter()
                                .zip(batch_distance.iter())
                                .map(|(&distid, dis)| {
                                    dis * kmeanspp.weights[distid].to_f64().unwrap()
                                })
                                .sum::<f64>();
                            *w8ed_dis += total_distance;
                        });
                });

            let mut distance = vec![vec![0_f64; centroids_size]; centroids_size];
            distance
                .par_iter_mut()
                .enumerate()
                .for_each(|(i, row)| {
                    row.iter_mut()
                        .enumerate()
                        .for_each(|(j, v)| {
                            *v += (weighted_distance[i][j] + weighted_distance[j][i])/(centroids_weight[i]+centroids_weight[j]).to_f64().unwrap();
                        });
                });
            distance
        };        
        
        // 7.ordered_centorids
        let mut ordered_centorids: Vec<Vec<usize>> = (0..centroids.len()).map(|_| (0..centroids.len()).collect()).collect();
        ordered_centorids
            .par_iter_mut()
            .enumerate()
            .for_each(|(row, ordered_ctrds)| {
                ordered_ctrds
                    .sort_by(|&a, &b| {
                        distances[row][a].partial_cmp(&distances[row][b]).unwrap()
                    })
            });

        (nriso_assign, dist_assign, ordered_centorids, distances)

    }

    fn load_terminal_wdistid_with_nriso() -> (Vec<usize>, usize){
        let street = T::NUM_STREET as usize - 1;

        // 确定数据库、列族，以及打开数据库
        let path = std::format!("data/{}", T::GAME_NAME);
        let options = {
            let mut options = Options::default();
            options.create_if_missing(false);
            options
        };
        let nriso2distid_cf = format!(
            "{}_nriso_{}_to_winning_distribution_id",
            T::GAME_NAME,
            street+1
        );
        let cf_names = vec!["default", &nriso2distid_cf];
        let cf_descriptors: Vec<_> = cf_names
            .iter()
            .map(|cf_name| {
                let mut cf_opt = Options::default();
                cf_opt.create_if_missing(false);
                ColumnFamilyDescriptor::new(cf_name.clone(), cf_opt)
            })
            .collect();
        let db = DBCommon::<SingleThreaded,_>::open_cf_descriptors_read_only(&options, &path , cf_descriptors, false).expect(&format!("打不开这个数据库{}的列族{}", path, nriso2distid_cf));
        let cf_handle = db.cf_handle(&nriso2distid_cf).expect(&format!("没有这个列族:{}", nriso2distid_cf));

        // 读street中的最后一位数据，代表的是distsize
        let recall_from = street;
        let isosize = T::instance().hand_isomorphism_size_street(street, recall_from);
        let distsize = db.get_cf(&cf_handle, (isosize as u32).to_be_bytes()).expect(&format!("isosize/key:{}在{}街的值为None", isosize, street)).unwrap();
        let distsize = u32::from_be_bytes((*distsize).try_into().unwrap()) as usize;
        
        // 把所有distid读出来，并且校验（校验的逻辑是最后一位是否是distsize，把所有数据去重之后长度是否为distsize）
        let mut dbcf_iter = db.iterator_cf(cf_handle, IteratorMode::Start);
        let mut nriso2distid = vec![distsize+1; isosize+1];
        for item in dbcf_iter {
            let (keybytes, valuebytes) = item.unwrap();
            assert!(keybytes.len() == 4 && valuebytes.len() == 4);
            let iso = u32::from_be_bytes((*keybytes).try_into().unwrap()) as usize;
            let distid = u32::from_be_bytes((*valuebytes).try_into().unwrap()) as usize;
            nriso2distid[iso] = distid;
        }
        assert_eq!(nriso2distid.pop().unwrap(), distsize);
        let unique: HashSet<_> = nriso2distid.iter().cloned().collect();
        assert_eq!(unique.len(), distsize);

        // 返回结果
        (nriso2distid, distsize)
    }

    fn load_terminal_wdist_with_id() -> Vec<[i64; 3]>{
        let street = T::NUM_STREET as usize - 1;
        // 确定数据库、列族，以及打开数据库
        let path = std::format!("data/{}", T::GAME_NAME);
        let options = {
            let mut options = Options::default();
            options.create_if_missing(false);
            options
        };
        let nrid2dist_cf = format!(
            "{}_nrid_{}_to_winning_distribution",
            T::GAME_NAME,
            street+1
        );
        let cf_names = vec!["default", &nrid2dist_cf];
        let cf_descriptors: Vec<_> = cf_names
            .iter()
            .map(|cf_name| {
                let mut cf_opt = Options::default();
                cf_opt.create_if_missing(false);
                ColumnFamilyDescriptor::new(cf_name.clone(), cf_opt)
            })
            .collect();
        let db = DBCommon::<SingleThreaded,_>::open_cf_descriptors_read_only(&options, &path , cf_descriptors, false).expect(&format!("打不开这个数据库{}的列族{}", path, nrid2dist_cf));
        let cf_handle = db.cf_handle(&nrid2dist_cf).expect(&format!("没有这个列族:{}", nrid2dist_cf));
        
        // 把所有distid读出来，并且校验（校验的逻辑是最后一位是否是distsize，把所有数据去重之后长度是否为distsize）
        let mut dbcf_iter = db.iterator_cf(cf_handle, IteratorMode::Start);
        let mut nrid2dist: Vec<[i64; 3]> = vec![];
        for item in dbcf_iter {
            let (keybytes, valuebytes) = item.unwrap();
            assert!(keybytes.len() == 4);
            let distid = u32::from_be_bytes((*keybytes).try_into().unwrap()) as usize;
            let dist: [i64; 3] = bincode::deserialize(&valuebytes).unwrap();
            nrid2dist.push(dist);
            assert_eq!(distid, nrid2dist.len()-1);
        }
        
        nrid2dist
    }

    //////////////////////////////////////////////
    //////////////////////////////////////////////
    fn nonterminal_street_cluster(street: usize, next_assign: &[usize], next_ordered_centorids: Vec<Vec<usize>>, next_distances: Vec<Vec<f64>> ,  centroids_size: usize, max_iter: usize) -> (Vec<usize>, Vec<usize>, Vec<Vec<usize>>, Vec<Vec<f64>>) {
        // 1.读数据
        // nriso2distid, nrid2dist, nrid2equity
        let (nriso2distid, distsize) = Self::load_pdistid_with_nriso(street);
        let nrid2dist = Self::load_pdist_with_id(street);
        assert_eq!(distsize, nrid2dist.len());
        let nrid2next_centroid: Vec<_> = nrid2dist
            .into_par_iter()
            .map(|dist| {
                assert_eq!(dist.len(), T::DECK.len() - T::HAND_LEN_STREET[street] as usize);
                dist.iter()
                    .map(|next_dist_id| {
                        next_assign[*next_dist_id as usize]
                    })
                    .collect::<Vec<usize>>()
            })
            .collect();
        {
            let unique: HashSet<_> = nrid2next_centroid.iter().cloned().collect();
            assert!(centroids_size <= unique.len());
        }

        // 2.找weight
        let nrid2weight: Arc<Vec<AtomicUsize>> = Arc::new((0..nrid2next_centroid.len()).into_par_iter().map(|_| AtomicUsize::new(0)).collect());
        nriso2distid
            .par_iter()
            .enumerate()
            .for_each( |(nriso, &distid)| {
                let recall_from=street;
                let adder = T::instance().hand_index_volumn(nriso, street, recall_from);
                nrid2weight[distid].fetch_add(adder, Ordering::Relaxed);
            });
        let nrid2weight: Vec<usize> = nrid2weight
            .par_iter()
            .map(|x| x.load(Ordering::Relaxed))
            .collect();
        let checksum = nrid2weight.par_iter().sum::<usize>();

        // 3.写两个函数
        let average_closure = {
            let next_centroids_size = next_ordered_centorids.len();
            
            move |pnt_idx: &[usize], pnts: &[Vec<usize>], w8s: &[usize]| -> Vec<(usize, f64)>{
                
                // let mut weight_sum = 0;
                // for &idx in pnt_idx {
                //     weight_sum += w8s[idx];  // 累加权重
                // }
                
                let centroid = 
                {
                    let mut centroid_usize: Vec<AtomicUsize> = (0..next_centroids_size).into_par_iter().map(|_| AtomicUsize::new(0)).collect();
                    let mut weight_sum: AtomicUsize = AtomicUsize::new(0);
                    pnt_idx
                        .par_iter()
                        .for_each(|&pntidx| {    
                            weight_sum.fetch_add(w8s[pntidx]*pnts[pntidx].len(), Ordering::Relaxed);
                            pnts[pntidx]
                                .iter()
                                .for_each(|&centroid_idx| {
                                    centroid_usize[centroid_idx].fetch_add(w8s[pntidx], Ordering::Relaxed);
                                });
                        });

                    let weight_sum = weight_sum.load(Ordering::Relaxed);

                    centroid_usize
                        .into_par_iter()
                        .map(|value| {
                            value.load(Ordering::Relaxed).to_f64().unwrap()/ weight_sum.to_f64().unwrap()
                        })
                        .collect::<Vec<_>>()
                };

                let mut centroid_sparse = centroid
                    .into_par_iter()
                    .enumerate()
                    .filter(|(_, component)| *component > 0.0 )
                    .collect::<Vec<_>>();

                centroid_sparse
            }
        };
        let distance_batch_closure = {
            let ordered_centorids = next_ordered_centorids.clone();
            let distances = next_distances.clone();
            
            move |pntidcs: &[usize], pnts: &[Vec<usize>], ctrd: &Vec<(usize, f64)>| -> Vec<f64> {
                let sparse_idcs = ctrd
                    .par_iter()
                    .map(|(idx, _)| *idx)
                    .collect::<Vec<_>>();

                let ordered_centroids_0_q_ctrd = ordered_centorids
                    .par_iter()
                    .map(|centroid_ordered_centroids| {
                        let part =  centroid_ordered_centroids
                            .iter()
                            .filter(|&centroid_idx| sparse_idcs.contains(centroid_idx))
                            .cloned()
                            .collect::<Vec<usize>>();
                        assert_eq!(part.len(), ctrd.len());

                        let sorted_index_part = {
                            let mut index_part = part
                            .into_iter()
                            .enumerate()
                            .collect::<Vec<_>>();
                            index_part
                                .sort_by(|a, b| {
                                    a.1.partial_cmp(&b.1).unwrap()
                                });
                            
                            let mut index_invindex_part = index_part
                                .into_iter()
                                .enumerate()
                                .collect::<Vec<_>>();
                            index_invindex_part
                                .sort_by(|a, b| {
                                    a.1.0.partial_cmp(&b.1.0).unwrap()
                                });

                            index_invindex_part
                        };

                        let (sorted_index, _): (Vec<usize>, (Vec<usize>, Vec<usize>)) = sorted_index_part.into_iter().unzip();
                            
                        sorted_index
                    })
                    .collect::<Vec<Vec<usize>>>();

                pntidcs
                    .par_iter()
                    // .iter()
                    .map(|&pntidx| {
                        let x = &pnts[pntidx];
                        let n = x.len();
                        let q = ctrd.len();
                        
                        let mut targets = vec![1.0/n as f64; n];
                        let mut mean_remaining = ctrd.clone();
                        let mut done = vec![false; n];
                        let mut tot_cost = 0.0;

                        for i in 0..q {
                            for j in 0..n {
                                if done[j] {
                                    continue;
                                }
    
                                let point_centroid = x[j];
                                let mean_centroid_0_q_ctrd = ordered_centroids_0_q_ctrd[point_centroid][i];
                                let mean_centroid = mean_remaining[mean_centroid_0_q_ctrd].0;
                                let amt_remaining = mean_remaining[mean_centroid_0_q_ctrd].1;
                                
                                if amt_remaining == 0.0 {
                                    continue
                                }
    
                                let d = distances[point_centroid][mean_centroid];

                                if amt_remaining < targets[j] {
                                    tot_cost += amt_remaining * d;
                                    targets[j] -= amt_remaining;
                                    mean_remaining[mean_centroid_0_q_ctrd].1 = 0.0;
                                } else {
                                    tot_cost += targets[j] * d;
                                    targets[j] = 0.0;
                                    mean_remaining[mean_centroid_0_q_ctrd].1 -= targets[j];
                                    done[j] = true;
                                }
                            }
                        }

                        tot_cost
                    })
                    .collect::<Vec<f64>>()
            }
        };

        // 4.kmeanspp
        let kmeanspp: WeightedKmeansPP<Vec<usize>, Vec<(usize, f64)>> = WeightedKmeansPP::<Vec<usize>, Vec<(usize, f64)>> {
            points: nrid2next_centroid,
            weights: nrid2weight,
            average_fn: Box::new(average_closure),
            distance_batch_fn: Box::new(distance_batch_closure),
        };
        let (dist_assign, centroid_pointidcs, centroids) = kmeanspp.kmeanspp_process(centroids_size, max_iter, true);

        // 5. dist_assign -> nriso
        let nriso_size = T::instance().hand_isomorphism_size_street(street, street);
        let nriso_assign = (0..nriso_size)
            .into_par_iter()
            .map(|nriso| {
                let nrid = nriso2distid[nriso];
                let bucket = dist_assign[nrid];
                bucket
            })
            .collect::<Vec<_>>();

        // 6. distance table
        // 构建
        let mut distances: Vec<Vec<f64>> ={
            let centroids_weight = centroid_pointidcs
                .par_iter()
                .map(|ctrd_pnts| {
                    let total_weight = ctrd_pnts
                        .iter()
                        .map(|&distid| {
                            kmeanspp.weights[distid]
                        })
                        .sum::<usize>();
                    total_weight
                })
                .collect::<Vec<_>>();

            let mut weighted_distance = vec![vec![0_f64; centroids_size]; centroids_size];
            weighted_distance
                .par_iter_mut()
                .enumerate()
                .for_each(|(ctrda_idx, disvec)| {
                    disvec
                        .iter_mut()
                        .enumerate()
                        .for_each(|(ctrdb_idx, w8ed_dis)| {
                            let batch_distance = (kmeanspp.distance_batch_fn)(centroid_pointidcs[ctrda_idx].as_ref(), kmeanspp.points.as_ref(), &centroids[ctrdb_idx]);
                            let total_distance = centroid_pointidcs[ctrda_idx]
                                .iter()
                                .zip(batch_distance.iter())
                                .map(|(&distid, dis)| {
                                    dis * kmeanspp.weights[distid].to_f64().unwrap()
                                })
                                .sum::<f64>();
                            *w8ed_dis += total_distance;
                        });
                });
            
            let mut distance = vec![vec![0_f64; centroids_size]; centroids_size];
            distance
                .par_iter_mut()
                .enumerate()
                .for_each(|(i, row)| {
                    row.iter_mut()
                        .enumerate()
                        .for_each(|(j, v)| {
                            *v += (weighted_distance[i][j] + weighted_distance[j][i])/(centroids_weight[i]+centroids_weight[j]).to_f64().unwrap();
                        });
                });
            distance
        };        
        
        // 7.ordered_centorids
        let mut ordered_centorids: Vec<Vec<usize>> = (0..centroids.len()).map(|_| (0..centroids.len()).collect()).collect();
        ordered_centorids
            .par_iter_mut()
            .enumerate()
            .for_each(|(row, ordered_ctrds)| {
                ordered_ctrds
                    .sort_by(|&a, &b| {
                        distances[row][a].partial_cmp(&distances[row][b]).unwrap()
                    })
            });

        (nriso_assign, dist_assign, ordered_centorids, distances)
    }
    
    fn load_pdistid_with_nriso(street:usize) -> (Vec<usize>, usize){
        // 确定数据库、列族，以及打开数据库
        let path = std::format!("data/{}", T::GAME_NAME);
        let options = {
            let mut options = Options::default();
            options.create_if_missing(false);
            options
        };
        let nriso2distid_cf = format!(
            "{}_nriso_{}_to_potential_distribution_id",
            T::GAME_NAME,
            street+1
        );
        let cf_names = vec!["default", &nriso2distid_cf];
        let cf_descriptors: Vec<_> = cf_names
            .iter()
            .map(|cf_name| {
                let mut cf_opt = Options::default();
                cf_opt.create_if_missing(false);
                ColumnFamilyDescriptor::new(cf_name.clone(), cf_opt)
            })
            .collect();
        let db = DBCommon::<SingleThreaded,_>::open_cf_descriptors_read_only(&options, &path , cf_descriptors, false).expect(&format!("打不开这个数据库{}的列族{}", path, nriso2distid_cf));
        let cf_handle = db.cf_handle(&nriso2distid_cf).expect(&format!("没有这个列族:{}", nriso2distid_cf));

        // 读street中的最后一位数据，代表的是distsize
        let recall_from = street;
        let isosize = T::instance().hand_isomorphism_size_street(street, recall_from);
        let distsize = db.get_cf(&cf_handle, (isosize as u32).to_be_bytes()).expect(&format!("isosize/key:{}在{}街的值为None", isosize, street)).unwrap();
        let distsize = u32::from_be_bytes((*distsize).try_into().unwrap()) as usize;
        
        // 把所有distid读出来，并且校验（校验的逻辑是最后一位是否是distsize，把所有数据去重之后长度是否为distsize）
        let mut dbcf_iter = db.iterator_cf(cf_handle, IteratorMode::Start);
        let mut nriso2distid = vec![distsize+1; isosize+1];
        for item in dbcf_iter {
            let (keybytes, valuebytes) = item.unwrap();
            assert!(keybytes.len() == 4 && valuebytes.len() == 4);
            let iso = u32::from_be_bytes((*keybytes).try_into().unwrap()) as usize;
            let distid = u32::from_be_bytes((*valuebytes).try_into().unwrap()) as usize;
            nriso2distid[iso] = distid;
        }
        assert_eq!(nriso2distid.pop().unwrap(), distsize);
        let unique: HashSet<_> = nriso2distid.iter().cloned().collect();
        assert_eq!(unique.len(), distsize);

        // 返回结果
        (nriso2distid, distsize)
    }

    fn load_pdist_with_id(street:usize) -> Vec<Vec<u32>>{
        // 确定数据库、列族，以及打开数据库
        let path = std::format!("data/{}", T::GAME_NAME);
        let options = {
            let mut options = Options::default();
            options.create_if_missing(false);
            options
        };
        let nrid2dist_cf = format!(
            "{}_nrid_{}_to_potential_distribution",
            T::GAME_NAME,
            street+1
        );
        let cf_names = vec!["default", &nrid2dist_cf];
        let cf_descriptors: Vec<_> = cf_names
            .iter()
            .map(|cf_name| {
                let mut cf_opt = Options::default();
                cf_opt.create_if_missing(false);
                ColumnFamilyDescriptor::new(cf_name.clone(), cf_opt)
            })
            .collect();
        let db = DBCommon::<SingleThreaded,_>::open_cf_descriptors_read_only(&options, &path , cf_descriptors, false).expect(&format!("打不开这个数据库{}的列族{}", path, nrid2dist_cf));
        let cf_handle = db.cf_handle(&nrid2dist_cf).expect(&format!("没有这个列族:{}", nrid2dist_cf));
        
        // 把所有distid读出来，并且校验（校验的逻辑是最后一位是否是distsize，把所有数据去重之后长度是否为distsize）
        let mut dbcf_iter = db.iterator_cf(cf_handle, IteratorMode::Start);
        let mut nrid2dist: Vec<Vec<u32>> = vec![];
        for item in dbcf_iter {
            let (keybytes, valuebytes) = item.unwrap();
            assert!(keybytes.len() == 4);
            let distid = u32::from_be_bytes((*keybytes).try_into().unwrap()) as usize;
            let dist: Vec<u32> = bincode::deserialize(&valuebytes).unwrap();
            nrid2dist.push(dist);
            assert_eq!(distid, nrid2dist.len()-1);
        }
        
        nrid2dist
    }

    pub fn save(&self, custom_name: &str) {
        let path_str = std::format!("data/CustomCluster/{}/PaEmd/{}", T::GAME_NAME, custom_name);
        let path = Path::new(path_str.as_str());
        if path.exists() {
            fs::remove_dir_all(path).unwrap();
        }
        fs::create_dir_all(path).unwrap();

        // 创建一个选项对象
        let mut opts = Options::default();
        // 设置数据库如果不存在则创建
        opts.create_if_missing(true);
        let mut db = DB::open(&opts, path).unwrap();
     
        self.kriso2bucket_street
            .iter()
            .zip(self.bucket_size_street.iter())
            .enumerate()
            .for_each(|(street, (kriso2bucket, bucket_size))|{
                let recall_from = if let AbstractAlgorithmStreet::PaEmd {..} = &self.abstr_configs[street] {
                    street
                }
                else if let AbstractAlgorithmStreet::Isomorphism{recall_from} = self.abstr_configs[street] {
                    recall_from
                }
                else {
                    panic!("不能到这里");
                };
                assert!(street >= recall_from, "street: {}, recall_from: {}", street, recall_from);
                save_cluster_bucket_street::<T>(&mut db, street, recall_from, kriso2bucket.as_ref(), *bucket_size);
            });
        save_cluster_configs_yaml(path, self.abstr_configs.as_ref());
    }
}

