use std::collections::HashMap;
use itertools::Itertools;

use std::sync::{Arc, Mutex, RwLock};
use std::cell::RefCell;
use super::cluster_alg::*;
use super::cluster_type::*;
use super::cluster_trait::*;
use super::simple_thread_pool::*;
use crate::database::db_type::{RWDist};

use crate::custom_games::royal231::{initial_game, Royal231, ROYAL_DECK};
use crate::featurizer::Featurizer;
use crate::featurizer::db_util::DbConnect;
use crate::game::component::*;
use crate::hand_isomorphism::{hand_indexer_t, hand_unindex, uint_fast32_t};
use crate::game::component::hand::*;
use crate::hand_isomorphism::{hand_index_last};

fn get_all_hands() -> Vec<Vec<u8>> {
    let deal_hole_street = &[2 as u8, 0, 0];
    let deal_board_street = &[0 as u8, 3, 1];
    let hand_len_street = get_hand_len_street::<3>(deal_hole_street, deal_board_street);
     
    let royal_deck = ROYAL_DECK.to_vec();
    let mut init_hands = Vec::new();
    let mut round_2_hands: Vec<Vec<u8>> = Vec::new();
    let mut round_3_hands: Vec<Vec<u8>> = Vec::new();
    royal_deck
        .iter()
        .cloned()
        .combinations(2)
        .for_each(|x|{init_hands.push(x);});
    
    let mut round_two = |hand:Vec<u8>|{
        royal_deck
        .iter()
        .filter(|&x| !hand.contains(x))
        .cloned()
        .collect::<Vec<u8>>()
        .iter()
        .cloned()
        .combinations(3)
        .for_each(|x|{
            let mut new_hand = hand.clone();
            new_hand.extend(x);
            round_2_hands.push(new_hand);
        });
    };

    let mut round_three = |hand:Vec<u8>|{
        royal_deck
        .iter()
        .filter(|&x| !hand.contains(x))
        .cloned()
        .collect::<Vec<u8>>()
        .iter()
        .cloned()
        .combinations(1)
        .for_each(|x|{
            let mut new_hand =hand.clone();
            new_hand.extend(x);
            round_3_hands.push(new_hand);
            });
    };

    for hand in init_hands {
        round_two(hand.to_vec());
    }
    //println!("{:?}", round_2_hands.len());

    for hand in round_2_hands {
        round_three(hand);
    }
    round_3_hands
}


pub fn get_points() -> Result<Vec<WinDistNodePtr>, String> {
    let mut points: Vec<WinDistNodePtr> = Vec::new();
    //
    type GameType = Royal231;
    initial_game();
    let game: &'static GameType = GameType::instance().as_ref();
    let street = GameType::NUM_STREET as usize - 1;
    // let recall_from = 0;
    let recall_from = GameType::NUM_STREET as usize - 1;

    // let street_x_recall_indexer 
    //     = &game.get_game_indexer().street_x_recall_indexers_1d[id_2d_to_1d(street, recall_from)];
    let isomorphism_size = game.hand_isomorphism_size_street(street, recall_from);

    println!("iso_size:{:?} \t recall_from:{:?} \t street:{:?}", 
    isomorphism_size, recall_from, street);
    let mut hands = get_all_hands();
    let mut weights: HashMap<u64, i32> = HashMap::new();
    for hand in hands{
        //let mut hand = vec![0 as u8; GameType::HAND_LEN];
        let x = game.hand_indexify(hand.as_ref(), street, recall_from) as u64;
        if let Some(value) = weights.get_mut(&x) {
            *value += 1;
        }
        else{
            weights.insert(x, 1);
        }
    }

    /////////////////////////////////////////////
    //生成231表表数据
    /////////////////////////////////////////////
    let mut ftrzr = Featurizer::<GameType>::new();
    for street_sentinel in (1..=GameType::NUM_STREET).rev() {
        // for street_sentinel in (1..=GameType::NUM_STREET).rev() {
        if street_sentinel < GameType::NUM_STREET {
            ftrzr.handle_street_potential_distribution(street_sentinel);
        }
        ftrzr.handle_street_winning_distribution(street_sentinel);
    }

    for street_sentinel in 1..=GameType::NUM_STREET {
        for recall_from_stentinel in 1..street_sentinel {
            ftrzr
                .handle_street_potential_trace_distribution(street_sentinel, recall_from_stentinel);
            ftrzr.handle_street_winning_trace_distribution(street_sentinel, recall_from_stentinel);
        }
    }

    let mut final_weights: HashMap<[i64; 3], i32> = HashMap::new();
    for (key, value) in &weights {
        let dist_id: u32 = ftrzr.query_dist_id_with_xriso(
            "Royal231_nriso_3_to_winning_distribution_id", 
            (*key) as u32 ).unwrap();
        let ptlvec: [i64; 3] = ftrzr.query_dist_with_id::<[i64; 3]>(
            "Royal231_nrid_3_to_winning_distribution", dist_id).unwrap();
        if let Some(pltvalue) = final_weights.get_mut(&ptlvec) {
            *pltvalue += value;
        }
        else{
            final_weights.insert(ptlvec, *value);
        }
    }
    /*
    for (key, value) in &weights {
        let dist_id: u32 = ftrzr.query_dist_id_with_xriso(
            "Royal231_nriso_3_to_winning_distribution_id", 
            (*key) as u32 ).unwrap();
        println!("{:?}", dist_id);
        let ptlvec: [i64; 3] = ftrzr.query_dist_with_id::<[i64; 3]>("Royal231_nrid_3_to_winning_distribution", dist_id).unwrap();
        points.push(Arc::new(WinDistNode::new(dist_id as i64, ptlvec, (*value) as i64 )));
    }*/
    
    let mut idx = 0;
    for (pltvec, count) in &final_weights {
        idx += 1;
        points.push(Arc::new(WinDistNode::new(idx, *pltvec, (*count) as i64 )));
    }

    Ok(points)
}