use dict::{Dict, DictIface};
use std::{collections::HashMap, fs::copy, ops::Deref, vec};

#[derive(Clone)]
struct CardConfig{
    pub suits:usize,
    pub ranks:usize,
}

impl CardConfig {
    pub fn card_to_suit(&self, card:u8)->usize{
        card as usize%self.suits 
    }
    
    pub fn card_to_rank(&self, card:u8)->usize{
        card as usize/self.suits
    }
    
    
    pub fn make_card(&self, suit:usize,rank:usize)->u8{
        return (rank*self.suits+suit) as u8;
    }
}

#[derive(Clone)]
pub struct HandIndexer {
    card_config: CardConfig,
    pub streets: usize,
    cards_per_street: Vec<usize>,
    hole_per_street: Vec<usize>,
    board_per_street: Vec<usize>,
    street_to_configuration: Vec<usize>,          // ?忘了
    pub configuration_to_offset: Vec<Vec<usize>>, // configuration_to_offset[street][configuation_index]
    pub configuration_to_size: Vec<Vec<usize>>,
    pub street_size: Vec<usize>,
    configuration_to_configurationindex: HashMap<Vec<Vec<usize>>, usize>,
    pub configurationindex_to_configuration: Vec<HashMap<usize, Vec<Vec<usize>>>>,
}

pub fn vector_flatten<'a>(hands: Vec<Vec<u8>>) -> Vec<u8> {
    let flatten_vec: Vec<u8> = hands.into_iter().flatten().collect();
    return flatten_vec;
}

fn was_larger(former: &Vec<usize>, current: &Vec<usize>) -> bool {
    // 比较两个configuration的大小，如果前一个大于等于后一个return true
    let length = former.len();
    for i in 0..length {
        // print!("{}",i);
        if former[i] > current[i] {
            return true;
        } else if former[i] == current[i] {
            continue;
        } else {
            return false;
        }
    }
    return true;
}

fn was_equal(former: &Vec<usize>, current: &Vec<usize>) -> bool {
    // 比较两个configuration的大小
    let length = former.len();
    for i in 0..length {
        // print!("{}",i);
        if former[i] > current[i] {
            return false;
        } else if former[i] == current[i] {
            continue;
        } else {
            return false;
        }
    }
    return true;
}

fn order_of_fullsuit_configuration(former: &Vec<Vec<usize>>, current: &Vec<Vec<usize>>) -> bool {
    // 如果前一个比后一个大return true，如果后一个大于前一个return false，不存在相等的情况
    let suits = former.len();
    for suit in 0..suits {
        if was_equal(&former[suit], &current[suit]) {
            continue;
        } else if was_larger(&former[suit], &current[suit]) {
            return true;
        } else {
            return false;
        }
    }
    panic!("equal full configuration");
}

// fn get_configurationindex(configuration:&Vec<Vec<usize>>)->usize{
//     let mut key=0;
//     for i in 0..configuration.len(){
//         for j in 0..configuration[i].len(){
//             key=key*10+configuration[i][j];
//         }
//     }
//     return key;
// }

fn factorial(m: usize, n: usize) -> usize {
    let mut res = 1;
    for i in m + 1..n + 1 {
        res *= i;
    }
    return res;
}

fn combinatorial(n: usize, m: usize) -> usize {
    if n < 0 || n < m {
        return 0;
    }
    return factorial(n - m, n) / factorial(0, m);
}

pub fn init_hand_indexer(
    suits: usize,
    ranks: usize,
    mut hole_per_street: Vec<usize>,
    mut board_per_street: Vec<usize>,
) -> HandIndexer {
    let mut cards_per_street = vec![];
    let mut cf_streets = 0;
    /* 交替 */
    for i in 0..hole_per_street.len() {
        if hole_per_street[i] != 0 {
            cards_per_street.push(hole_per_street[i]);
            cf_streets += 1;
        }
        if board_per_street[i] != 0 {
            cards_per_street.push(board_per_street[i]);
            cf_streets += 1;
        }
    }
    /* flatten
    for i in 0..hole_per_street.len(){
        if hole_per_street[i] != 0{
            cards_per_street.push(hole_per_street[i]);
            cf_streets+=1;
        }
    }
    for i in 0..board_per_street.len(){
        if board_per_street[i]!=0{
            cards_per_street.push(board_per_street[i]);
            cf_streets+=1;
        }
    }*/

    let mut indexer = HandIndexer {
        card_config: CardConfig {
            suits: suits,
            ranks: ranks,
        },
        streets: cf_streets,
        street_to_configuration: vec![0; cf_streets],
        cards_per_street,
        hole_per_street,
        board_per_street,
        configuration_to_offset: vec![vec![]; cf_streets],
        configuration_to_size: vec![vec![]; cf_streets],
        street_size: vec![0; cf_streets],
        configuration_to_configurationindex: HashMap::new(),
        configurationindex_to_configuration: vec![HashMap::new(); cf_streets],
    };
    let configurations: Vec<Vec<usize>> = vec![vec![0; indexer.streets]; indexer.card_config.suits];
    indexer.enumerte_configuration(0, indexer.cards_per_street[0], 0, configurations);
    indexer.configuration_order();
    indexer.configuration_to_size = indexer.configuration_to_offset.clone();
    indexer.update_offset();
    // for of in indexer.configuration_to_offset[1].iter(){
    //     println!("off {}",of);
    // }
    indexer
}

impl HandIndexer {
    fn get_cf_streets(&self, street: usize) -> usize {
        assert!(street <= self.hole_per_street.len());
        let mut cf_streets = 0;
        for i in 0..(street) {
            if self.hole_per_street[i] != 0 {
                cf_streets += 1;
            }
        }
        for i in 0..(street) {
            if self.board_per_street[i] != 0 {
                cf_streets += 1;
            }
        }
        return cf_streets;
    }

    // fn reverse_get_configurationindex(&mut self,index:usize)->Vec<Vec<usize>>{
    //     let res=vec![];
    //     for i in 0..self.card_config.suits{
    //         let suit_configuration=vec![];
    //         for j in 0..self.streets{
    //             usize%10
    //         }
    //     }
    // }

    fn total_colex(&mut self, configuration: &Vec<Vec<usize>>, street: usize) {
        let mut equal = vec![false; self.card_config.suits];
        for i in 0..self.card_config.suits - 1 {
            if was_equal(&configuration[i], &configuration[i + 1]) {
                equal[i] = true;
            }
        }

        let mut suit = 0;
        let mut offset = 1;

        while suit < self.card_config.suits {
            let mut same_suit = 1; // 相同的suit的数目
            for i in suit..self.card_config.suits - 1 {
                if equal[i] {
                    same_suit += 1;
                } else {
                    break;
                }
            }
            let mut remaining_rank = self.card_config.ranks;
            let mut combination_num = 1;
            for i in 0..configuration[suit].len() {
                combination_num *= combinatorial(remaining_rank, configuration[suit][i]);
                if remaining_rank < configuration[suit][i] {
                    // print!("");
                }
                remaining_rank -= configuration[suit][i];
            }

            // assert_eq!(combination_num,self.combination_num(configuration[suit].clone()));
            // let combination_num= self.combination_num(configuration[suit].clone()); //可以直接用这个函数

            offset *= combinatorial(combination_num + same_suit - 1, same_suit);
            suit += same_suit;
        }
        self.configuration_to_offset[street].push(offset);
        // println!("offset {}",offset)
    }

    fn update_offset(&mut self) {
        // 原本configuration-to-offset存储的是configuration的size
        for i in 0..self.streets {
            let mut accum = 0;
            for j in 0..self.street_to_configuration[i] {
                accum += self.configuration_to_offset[i][j];
                self.configuration_to_offset[i][j] = accum - self.configuration_to_offset[i][j];
            }
            self.street_size[i] = accum;
        }
    }

    fn add_dict(&mut self, configuration: &Vec<Vec<usize>>, value: usize, street: usize) {
        // let key = get_configurationindex(configuration);
        // self.configuration_to_configurationindex.add(key.to_string(),value);
        // self.configurationindex_to_configuration.add(value.to_string(),key);

        self.configuration_to_configurationindex
            .insert(configuration.to_vec(), value);
        self.configurationindex_to_configuration[street].insert(value, configuration.to_vec());
    }

    fn configuration_order(&mut self) {
        // index应该是顺序的，就说大的configuration的index应该更大
        for street in 0..self.streets {
            // self.configuration_to_configurationindex;
            // self.configurationindex_to_configuration[street];
            // self.configuration_to_offset[street];

            let length = self.configuration_to_offset[street].len();
            while true {
                let mut whether_finished = true;
                for key in 0..length - 1 {
                    let former = self.configurationindex_to_configuration[street]
                        .get(&key)
                        .unwrap()
                        .clone();
                    let current = self.configurationindex_to_configuration[street]
                        .get(&(key + 1))
                        .unwrap()
                        .clone();
                    if order_of_fullsuit_configuration(&former, &current) {
                        // println!("{}>{}",key,key+1);
                        // println!("{:?}>{:?}",former,current);
                        whether_finished = false;

                        self.configuration_to_configurationindex
                            .insert(former.clone(), key + 1);
                        self.configuration_to_configurationindex
                            .insert(current.clone(), key);

                        self.configurationindex_to_configuration[street]
                            .insert(key, current.clone());
                        self.configurationindex_to_configuration[street]
                            .insert(key + 1, former.clone());

                        let offset = self.configuration_to_offset[street][key];
                        self.configuration_to_offset[street][key] =
                            self.configuration_to_offset[street][key + 1];
                        self.configuration_to_offset[street][key + 1] = offset;
                        // println!("{:?}",self.configurationindex_to_configuration[street]);
                    };
                }
                if whether_finished {
                    break;
                }
            }
        }

        // let mut insert_position=value;
        // for i in 0..value{ // 遍历先前的index 0~value-1
        //     let k = value-i-1;
        //     let former=self.configurationindex_to_configuration[street].get(&k).unwrap();
        //     if order_of_fullsuit_configuration(former, configuration){
        //     }
        //     else{
        //         insert_position=k+1;
        //     }
        // }

        // for i in insert_position..value{ //把k+1到value-1全部往后挪动一位
        //     let config=self.configurationindex_to_configuration[street].get(&i).unwrap();
        //     self.configuration_to_configurationindex.insert(config.to_vec(), i+1);
        // }
        // for i in insert_position..value{ //把k+1到value-1全部往后挪动一位
        //     let k =value-1-i+insert_position;
        //     let config=self.configurationindex_to_configuration[street].get(&k).unwrap().clone();
        //     self.configurationindex_to_configuration[street].insert(k+1, config);
        // }

        // self.configuration_to_configurationindex.insert(configuration.to_vec(), insert_position);
        // self.configurationindex_to_configuration[street].insert(insert_position,configuration.to_vec());
    }

    fn enumerte_configuration(
        &mut self,
        suit: usize,
        remaining: usize,
        street: usize,
        mut configuration: Vec<Vec<usize>>,
    ) {
        if suit > 1 {
            if was_larger(&configuration[suit - 2], &configuration[suit - 1]) {
            } else {
                return ();
            }
        }
        if suit == self.card_config.suits {
            // 卡牌已经分配完毕
            self.add_dict(&configuration, self.street_to_configuration[street], street);
            self.street_to_configuration[street] += 1; // 更新street_to_configuration
                                                       // println!("configuration {:?}",configuration);
            self.total_colex(&configuration, street);
            if (street + 1) < self.streets {
                self.enumerte_configuration(
                    0,
                    self.cards_per_street[street + 1],
                    street + 1,
                    configuration.clone(),
                );
            }
        } else {
            let mut min = 0;
            let mut max = self.card_config.ranks;

            if street > 0 {
                max = self.card_config.ranks - configuration[suit].iter().sum::<usize>();
            }

            if max > remaining {
                max = remaining;
            }
            if suit == self.card_config.suits - 1 {
                min = remaining;
            }
            for i in min..(max + 1) {
                configuration[suit][street] = i;
                self.enumerte_configuration(suit + 1, remaining - i, street, configuration.clone());
            }
        }
    }

    fn compute_colex_for_suit(&self, suit_hand: &mut Vec<Vec<usize>>) -> usize {
        let streets = suit_hand.len();
        if streets != self.streets {
            // println!("注意 hands和hand_indexer不匹配")
        }
        let mut colex = 0;
        let mut multipler = 1;
        let mut remaining_rank = self.card_config.ranks;
        let mut used_rank = vec![]; //记录出现过的rank
                                    /*
                                    for i in suit_hand.iter_mut(){
                                        for j in &mut *i{
                                            for k in &used_rank{
                                                if *k<*j{
                                                    *j-=1;
                                                }
                                            }
                                        }
                                        for j in &mut *i{
                                            used_rank.push(j.clone());
                                        }
                                    }
                                    */
        // println!("suit hand{:?}",suit_hand);

        for mut i in suit_hand.iter_mut() {
            i.sort();
            i.reverse();
            let u_r_len = used_rank.len();
            let mut remaining = i.len();
            for j in i.iter() {
                let mut rank_to_minus = 0;
                for k in 0..u_r_len {
                    if used_rank[k] < *j {
                        rank_to_minus += 1;
                    }
                }
                used_rank.push(*j);

                colex += combinatorial(*j - rank_to_minus, remaining) * multipler; // 比j小的rank其实是j个而不是j-1
                remaining -= 1;
            }
            multipler *= combinatorial(remaining_rank, i.len());
            remaining_rank -= i.len();
        }
        // println!("{}",colex);

        return colex;
    }

    fn combination_num(&self, configuation: &Vec<usize>) -> usize {
        // 计算给定configuration后可能的rank的组合
        let mut res = 1;
        let mut remaining_rank = self.card_config.ranks;
        for i in configuation {
            res *= combinatorial(remaining_rank, *i);
            remaining_rank -= *i;
        }
        return res;
    }

    pub fn compute_isomorphism(&self, hole: &[u8], board: &[u8], mut streets: usize) -> usize {
        streets += 1;
        assert!(streets <= self.streets);
        let mut suit_to_hands: Vec<Vec<Vec<usize>>> =
            vec![vec![vec![]; self.streets]; self.card_config.suits]; // 每一个花色各个street的rank
        let mut configuration: Vec<Vec<usize>> =
            vec![vec![0; self.streets]; self.card_config.suits]; // 每一个花色的configuration
                                                                 /* 交替 */
        let mut hole_index = 0;
        let mut board_index = 0;
        let mut cf_street = 0;
        for street in 0..streets {
            for j in 0..self.hole_per_street[street] {
                let suit = self.card_config.card_to_suit(hole[hole_index]);
                let rank = self.card_config.card_to_rank(hole[hole_index]);
                configuration[suit][cf_street] += 1;
                suit_to_hands[suit][cf_street].push(rank);
                hole_index += 1;
            }
            if self.hole_per_street[street] > 0 {
                cf_street += 1;
            }
            for j in 0..self.board_per_street[street] {
                let suit = self.card_config.card_to_suit(board[board_index]);
                let rank = self.card_config.card_to_rank(board[board_index]);
                configuration[suit][cf_street] += 1;
                suit_to_hands[suit][cf_street].push(rank);
                board_index += 1;
            }
            if self.board_per_street[street] > 0 {
                cf_street += 1;
            }
        }

        /* flatten
        let mut index = 0;
        let mut cf_street = 0;
        for street in 0..streets{
            for j in 0..self.hole_per_street[street]{
                let suit=self.card_config.card_to_suit(hole[index]);
                let rank=self.card_config.card_to_rank(hole[index]);
                configuration[suit][cf_street]+=1;
                suit_to_hands[suit][cf_street].push(rank);
                index+=1;
            }
            if self.hole_per_street[street]>0{
                cf_street+=1;
            }
        }

        index = 0;
        for street in 0..streets{
            for j in 0..self.board_per_street[street]{
                let suit=self.card_config.card_to_suit(board[index]);
                let rank=self.card_config.card_to_rank(board[index]);
                configuration[suit][cf_street]+=1;
                suit_to_hands[suit][cf_street].push(rank);
                index+=1;
            }
            if self.board_per_street[street]>0{
                cf_street+=1;
            }
        }
        */
        streets = self.get_cf_streets(streets); // cf_streets

        // println!("configuration{:?}",configuration);
        // println!("{:?}{:?}",configuration,suit_to_hands);
        let mut change = true;
        while change {
            // 对configuration进行冒泡排序
            change = false;
            for i in 0..configuration.len() - 1 {
                if was_larger(&configuration[i], &configuration[i + 1]) {
                } else {
                    let c = configuration[i].clone();
                    configuration[i] = configuration[i + 1].clone();
                    configuration[i + 1] = c;

                    let c = suit_to_hands[i].clone();
                    suit_to_hands[i] = suit_to_hands[i + 1].clone();
                    suit_to_hands[i + 1] = c;

                    change = true;
                }
            }
        }
        // println!("排序后的configuration{:?} 排序后每个花色的手牌{:?}",configuration,suit_to_hands);

        let mut equal = vec![false; self.card_config.suits];
        for i in 0..self.card_config.suits - 1 {
            if was_equal(&configuration[i], &configuration[i + 1]) {
                equal[i] = true;
            }
        }
        let mut colexes = vec![];
        let mut index = 0;
        let mut multi_colex = vec![];
        for mut i in suit_to_hands {
            //根据configuration是否相同，对花色进行分组
            let res = self.compute_colex_for_suit(&mut i); //计算每一个suit单独的colex
            multi_colex.push(res);
            if index < self.card_config.suits - 1 {
                if equal[index] {
                } else {
                    colexes.push(multi_colex);
                    multi_colex = vec![];
                }
            } else {
                colexes.push(multi_colex);
                break;
            }
            index += 1;
        }
        // println!("colexes {:?}",colexes);

        let mut multipler = 1;
        let mut index = 0;
        let mut colex = 0;
        for mut i in colexes {
            let mut remaining_ = i.len();
            i.sort();
            i.reverse();
            // println!("{:?}",i);
            for j in &i {
                index += 1;
                colex += combinatorial(j + remaining_ - 1, remaining_) * multipler;
                remaining_ -= 1;
            }
            let combination_num = self.combination_num(&configuration[index - 1]);
            multipler *= combinatorial(combination_num + i.len() - 1, i.len());
        }

        // let configurationindex= get_configurationindex(&configuration);
        // let mut offset = self.configuration_to_configurationindex.get(&configurationindex.to_string()).unwrap().clone();
        let mut offset = self
            .configuration_to_configurationindex
            .get(&configuration)
            .unwrap()
            .clone();

        offset = self.configuration_to_offset[streets - 1][offset];
        // println!("offset {}",offset);
        offset + colex
    }

    fn enumerate_multi_colex(
        &self,
        remaining: usize,
        data: Vec<usize>,
        same_c: usize,
        save: &mut Vec<Vec<usize>>,
    ) {
        if data.len() == same_c {
            save.push(data.clone());
            return ();
        }
        for i in 0..remaining {
            let mut copy_data = data.clone();
            copy_data.push(i);
            self.enumerate_multi_colex(i + 1, copy_data, same_c, save);
        }
    }

    pub fn iso_size_street(&self, street: usize) -> usize {
        let cf_street = self.get_cf_streets(street+1);
        self.street_size[cf_street-1]
    }

    pub fn reduction_class_num(&self, colex: usize, mut streets: usize) -> usize {
        // 将colex还原成卡牌，所在类的大小
        streets += 1;
        streets = self.get_cf_streets(streets);
        assert!(streets <= self.streets);
        let mut configurationindex = 0;

        for i in &self.configuration_to_offset[streets - 1] {
            if colex < *i {
                break;
            }
            configurationindex += 1;
        }
        configurationindex -= 1;
        let configuration = self.configurationindex_to_configuration[streets - 1]
            .get(&configurationindex)
            .unwrap();
        let mut equal = vec![false; self.card_config.suits]; // 满足交换的条件1
        for i in 0..self.card_config.suits - 1 {
            if was_equal(&configuration[i], &configuration[i + 1]) {
                equal[i] = true;
            }
        }

        let mut group_configuration = vec![]; // 根据configuration的大小进行分组
        let mut group = vec![];
        group.push(configuration[0].clone());
        for i in 0..self.card_config.suits - 1 {
            if equal[i] {
            } else {
                group_configuration.push(group);
                group = vec![];
            }
            group.push(configuration[i + 1].clone());
        }
        group_configuration.push(group);
        let mut copy_colex = colex - self.configuration_to_offset[streets - 1][configurationindex];
        let mut multi_colex = vec![];
        for i in 0..group_configuration.len() {
            let c_num = self.combination_num(&group_configuration[i][0]);
            let group_c_num = combinatorial(
                // 组合的数目
                c_num + group_configuration[i].len() - 1,
                group_configuration[i].len(),
            );
            multi_colex.push(copy_colex % group_c_num);
            copy_colex = (copy_colex - multi_colex[multi_colex.len() - 1]) / group_c_num;
        }
        // 知道每个multi colex的index
        let mut suit_colex = vec![]; // // 满足交换的条件2
        for i in 0..multi_colex.len() {
            let c_num = self.combination_num(&group_configuration[i][0]);
            let mut save = vec![vec![]; 0];
            self.enumerate_multi_colex(c_num, vec![], group_configuration[i].len(), &mut save);
            let mut res = vec![];
            for m_colex in save {
                let mut c = 0;
                for j in 0..m_colex.len() {
                    c += combinatorial(m_colex[j] + m_colex.len() - j - 1, m_colex.len() - j)
                }
                if c == multi_colex[i] {
                    res = m_colex;
                    break;
                }
            }
            for j in res {
                suit_colex.push(j);
            }
        }
        //知道每个suit的suit colex了已经
        // println!(
        //     "suit colex {:?} configuration {:?}",
        //     suit_colex, configuration
        // );
        let mut group = vec![];
        let mut group_size = 1;
        for i in 0..self.card_config.suits - 1 {
            if suit_colex[i] == suit_colex[i + 1] && equal[i] {
                group_size += 1;
            } else {
                group.push(group_size);
                group_size = 1;
            }
        }
        let mut m = self.card_config.suits;
        let mut res = 1;
        for i in group {
            res *= combinatorial(m, i);
            m -= i;
        }
        res
    }

    pub fn reduction(&self, colex: usize, mut streets: usize) -> Vec<Vec<u8>> {
        // 将colex还原成卡牌
        streets += 1;
        streets = self.get_cf_streets(streets);
        assert!(streets <= self.streets);
        let mut configurationindex = 0;

        for i in &self.configuration_to_offset[streets - 1] {
            if colex < *i {
                break;
            }
            configurationindex += 1;
        }
        configurationindex -= 1;

        let configuration = self.configurationindex_to_configuration[streets - 1]
            .get(&configurationindex)
            .unwrap();
        let mut equal = vec![false; self.card_config.suits]; // 满足交换的条件1
        for i in 0..self.card_config.suits - 1 {
            if was_equal(&configuration[i], &configuration[i + 1]) {
                equal[i] = true;
            }
        }

        let mut group_configuration = vec![]; // 根据configuration的大小进行分组
        let mut group = vec![];
        group.push(configuration[0].clone());
        for i in 0..self.card_config.suits - 1 {
            if equal[i] {
            } else {
                group_configuration.push(group);
                group = vec![];
            }
            group.push(configuration[i + 1].clone());
        }
        group_configuration.push(group);
        let mut copy_colex = colex - self.configuration_to_offset[streets - 1][configurationindex];
        let mut multi_colex = vec![];
        for i in 0..group_configuration.len() {
            let c_num = self.combination_num(&group_configuration[i][0]);
            let group_c_num = combinatorial(
                // 组合的数目
                c_num + group_configuration[i].len() - 1,
                group_configuration[i].len(),
            );
            multi_colex.push(copy_colex % group_c_num);
            copy_colex = (copy_colex - multi_colex[multi_colex.len() - 1]) / group_c_num;
        }
        // 知道每个multi colex的index
        let mut suit_colex = vec![]; // // 满足交换的条件2
        for i in 0..multi_colex.len() {
            let c_num = self.combination_num(&group_configuration[i][0]);
            let mut save = vec![vec![]; 0];
            self.enumerate_multi_colex(c_num, vec![], group_configuration[i].len(), &mut save);
            let mut res = vec![];
            for m_colex in save {
                let mut c = 0;
                for j in 0..m_colex.len() {
                    c += combinatorial(m_colex[j] + m_colex.len() - j - 1, m_colex.len() - j)
                }
                if c == multi_colex[i] {
                    res = m_colex;
                    break;
                }
            }
            for j in res {
                suit_colex.push(j);
            }
        }
        //知道每个suit的suit colex了已经
        // println!(
        //     "suit colex {:?} configuration {:?}",
        //     suit_colex, configuration
        // );
        let mut res = vec![];
        for i in 0..suit_colex.len() {
            let mut save = vec![];
            self.enumurate_suit_hands(
                &configuration[i],
                self.card_config.ranks,
                vec![vec![]; streets],
                &mut save,
                0,
            );
            // println!("{:?}",save);
            for mut j in save {
                if self.compute_colex_for_suit(&mut j) == suit_colex[i] {
                    res.push(j);
                    break;
                }
            }
        }
        // println!("reduction各个花色结果{:?}",res);
        let mut result = vec![vec![]; streets];
        for r in 0..streets {
            for suit in 0..res.len() {
                for rank in &res[suit][r] {
                    result[r].push(self.card_config.make_card(suit, *rank))
                }
            }
        }
        return result;
        // return res;
        //

        let mut list_suit_to_hand: Vec<Vec<Vec<u8>>> = vec![];
        self.enumerte_hands(
            streets,
            &configuration,
            vec![vec![vec![]; streets]; self.card_config.suits],
            0,
            0,
            &mut list_suit_to_hand,
            self.card_config.ranks,
        );
        let mut num = 0;
        if configurationindex == self.configuration_to_offset[streets - 1].len() - 1 {
            num = self.street_size[streets - 1]
                - self.configuration_to_offset[streets - 1][configurationindex]
        } else {
            num = self.configuration_to_offset[streets - 1][configurationindex + 1]
                - self.configuration_to_offset[streets - 1][configurationindex]
        }
        // println!("{:?}",list_suit_to_hand);
        // println!("{:?}",configuration);
        assert_eq!(list_suit_to_hand.len(), num);

        for i in list_suit_to_hand {
            // println!("{}",self.compute_isomorphism(i.clone()));
            let flatten_vec: Vec<u8> = vector_flatten(i);
            if self.compute_isomorphism(&flatten_vec, &vec![], streets) == colex {
                return i;
            }
        }
        return vec![vec![]];
    }

    fn enumurate_suit_hands(
        &self,
        configuration: &Vec<usize>,
        remaining: usize,
        suit_hands: Vec<Vec<usize>>,
        save: &mut Vec<Vec<Vec<usize>>>,
        street: usize,
    ) {
        if street == suit_hands.len() {
            save.push(suit_hands);
            return ();
        }
        if suit_hands[street].len() < configuration[street] {
            for i in 0..remaining {
                let mut whether_continue = false;
                for r in 0..street {
                    if suit_hands[r].contains(&i) {
                        whether_continue = true;
                    }
                }
                if whether_continue {
                    continue;
                }
                let mut copy = suit_hands.clone();
                copy[street].push(i);
                if street > 0 && copy[street] == copy[street - 1] {
                    panic!("error")
                }
                self.enumurate_suit_hands(configuration, i, copy, save, street);
            }
        } else {
            self.enumurate_suit_hands(
                configuration,
                self.card_config.ranks,
                suit_hands.clone(),
                save,
                street + 1,
            )
        }
    }

    fn enumerte_hands(
        &self,
        streets: usize,
        configuration: &Vec<Vec<usize>>,
        hands: Vec<Vec<Vec<u8>>>,
        suit: usize,
        street: usize,
        list_suit_to_hand: &mut Vec<Vec<Vec<u8>>>,
        remaining_rank: usize,
    ) {
        if street == streets {
            let mut res = vec![vec![]; streets];
            let mut equal = vec![false; self.card_config.suits];
            for i in 0..self.card_config.suits - 1 {
                if was_equal(&configuration[i], &configuration[i + 1]) {
                    equal[i] = true;
                }
            }
            for i in 0..self.card_config.suits - 1 {
                if equal[i] {
                    let mut hands_1: Vec<Vec<Vec<usize>>> =
                        vec![vec![vec![]; hands[i].len()]; self.card_config.suits];
                    for street in 0..hands[i].len() {
                        for x in &hands[i][street] {
                            hands_1[i][street].push(self.card_config.card_to_rank(*x as u8));
                        }
                        for x in &hands[i + 1][street] {
                            hands_1[i + 1][street].push(self.card_config.card_to_rank(*x as u8));
                        }
                    }
                    if self.compute_colex_for_suit(&mut hands_1[i])
                        < self.compute_colex_for_suit(&mut hands_1[i + 1])
                    {
                        return ();
                    }
                }
            }
            // println!("{:?}",hands);
            for suit in 0..self.card_config.suits {
                for r in 0..streets {
                    for k in &hands[suit][r] {
                        res[r].push(*k);
                    }
                }
            }
            list_suit_to_hand.push(res.clone());
            return ();
        }
        if suit < self.card_config.suits {
            if hands[suit][street].len() < configuration[suit][street] {
                let min = configuration[suit][street] - hands[suit][street].len();
                for rank in 0..remaining_rank {
                    let mut whether_continue = false;
                    for r in 0..street {
                        if hands[suit][r].contains(&self.card_config.make_card(suit, rank)) {
                            whether_continue = true;
                        }
                    }
                    if whether_continue {
                        continue;
                    }
                    let mut hands_copy = hands.clone();
                    hands_copy[suit][street].push(self.card_config.make_card(suit, rank));
                    if street > 0 && hands_copy[suit][street] == hands_copy[suit][street - 1] {
                        panic!("error")
                    }

                    self.enumerte_hands(
                        streets,
                        configuration,
                        hands_copy,
                        suit,
                        street,
                        list_suit_to_hand,
                        rank,
                    );
                }
            } else {
                self.enumerte_hands(
                    streets,
                    configuration,
                    hands.clone(),
                    suit + 1,
                    street,
                    list_suit_to_hand,
                    self.card_config.ranks,
                );
            }
        } else if street < streets {
            self.enumerte_hands(
                streets,
                configuration,
                hands.clone(),
                0,
                street + 1,
                list_suit_to_hand,
                self.card_config.ranks,
            );
        }
    }
}

#[cfg(test)]
#[test]
fn it_works() {
    use crate::hand_isomorphism::card::CardConfig;
    use std::{hint, vec};

    assert_eq!(was_larger(&vec![2, 0, 1], &vec![1, 1, 3]), true);
    assert_eq!(was_larger(&vec![2, 0, 1], &vec![3, 1, 3]), false);
    assert_eq!(factorial(0, 0), 1);
    assert_eq!(factorial(0, 5), 5 * 4 * 3 * 2);
    assert_eq!(combinatorial(5, 2), 10);

    let card_config = CardConfig {
        suits: 4,
        ranks: 13,
    };

    let mut flop_indexer = HandIndexer {
        card_config: CardConfig {
            suits: 4,
            ranks: 13,
        },
        streets: 2,
        street_to_configuration: vec![0; 2],
        cards_per_street: vec![2, 3, 0, 0],
        hole_per_street: vec![2, 0, 0, 0],
        board_per_street: vec![0, 3, 0, 0],
        configuration_to_offset: vec![vec![]; 2],
        configuration_to_size: vec![vec![]; 2],
        street_size: vec![0; 2],
        configuration_to_configurationindex: HashMap::new(),
        configurationindex_to_configuration: vec![HashMap::new(); 2],
    };

    let configurations: Vec<Vec<usize>> =
        vec![vec![0; flop_indexer.streets]; flop_indexer.card_config.suits];
    flop_indexer.enumerte_configuration(
        0,
        flop_indexer.cards_per_street[0],
        0,
        configurations.clone(),
    );
    // println!("{:?}",flop_indexer.street_to_configuration);
    // println!("{:?}",flop_indexer.configuration_to_offset);
    flop_indexer.configuration_order();
    flop_indexer.update_offset();
    // println!("{:?}",flop_indexer.configuration_to_offset);
    // println!("{:?}",flop_indexer.street_size);
    // println!("{:?}",h_i.configuration_to_configurationindex);

    assert_eq!(flop_indexer.compute_isomorphism(&[1, 14], &[], 0), 6);
    // println!("{:?}",flop_indexer.reduction(168, 0));

    let mut res = vec![];
    let mut res_reduction = vec![];
    for i in 0..flop_indexer.card_config.ranks {
        for j in 0..flop_indexer.card_config.ranks {
            let mut cards = vec![];
            cards.push(card_config.make_card(0, flop_indexer.card_config.ranks - 1 - j));
            let suit = (j <= i);
            if suit {
                let suit = 1;
                cards.push(card_config.make_card(suit, flop_indexer.card_config.ranks - 1 - i));
            } else {
                let suit = 0;
                cards.push(card_config.make_card(suit, flop_indexer.card_config.ranks - 1 - i));
            }
            res.push(flop_indexer.compute_isomorphism(&cards.clone(), &vec![], 0));
            res_reduction.push(vec![
                flop_indexer.reduction(res[res.len() - 1], 0),
                vec![cards.clone()],
            ]);
            // res_reduction.push(vec![vec![cards.clone()]]);
            // assert_eq!(flop_indexer.reduction(res[res.len()-1],1),vec![cards]);
        }
        // println!();
    }
    let mut index = 0;
    for i in 0..flop_indexer.card_config.ranks {
        for j in 0..flop_indexer.card_config.ranks {
            // print!("{} ",res[index]);
            // print!("{:?}",res_reduction[index]);
            index += 1;
        }
        // println!();
    }

    assert_eq!(flop_indexer.street_size[0], 169);
    assert_eq!(flop_indexer.street_size[1], 1286792);
    // println!("{:?}",flop_indexer.reduction(168, 0));
    // println!("{:?}",flop_indexer.reduction(78, 0));

    let mut river_indexer = HandIndexer {
        card_config: CardConfig {
            suits: 4,
            ranks: 13,
        },
        streets: 4,
        street_to_configuration: vec![0; 4],
        cards_per_street: vec![2, 3, 1, 1],
        hole_per_street: vec![2, 0, 0, 0],
        board_per_street: vec![0, 3, 1, 1],
        configuration_to_offset: vec![vec![]; 4],
        configuration_to_size: vec![vec![]; 4],
        street_size: vec![0; 4],
        configuration_to_configurationindex: HashMap::new(),
        configurationindex_to_configuration: vec![HashMap::new(); 4],
    };
    let configurations: Vec<Vec<usize>> =
        vec![vec![0; river_indexer.streets]; river_indexer.card_config.suits];
    river_indexer.enumerte_configuration(
        0,
        river_indexer.cards_per_street[0],
        0,
        configurations.clone(),
    );
    river_indexer.configuration_order();
    river_indexer.update_offset();
    assert_eq!(river_indexer.street_size[0], 169);
    assert_eq!(river_indexer.street_size[1], 1286792);
    assert_eq!(river_indexer.street_size[2], 55190538);
    assert_eq!(river_indexer.street_size[3], 2428287420);
    // println!("{:?}",river_indexer.street_to_configuration);
    // println!("{:?}",river_indexer.configuration_to_offset);
    // let co=river_indexer.compute_isomorphism(vec![vec![39,2],vec![3,4,19]]);
    // assert_eq!(co,631471);
    // println!("{}",river_indexer.compute_isomorphism(vec![vec![2,3],vec![4,5,6],vec![7],vec![8]]));
    // println!("waiting");
    // println!("{} {:?}",co,river_indexer.reduction(co, 2));
    return;
}
