use std::sync::Arc;
use crate::database::db_type::{RWDist, WinDistType};

use super::cluster_type::{WinDistNode, WinDistNodePtr, WinDistCenter, WinDistCenterPtr};
use super::cluster_alg::{cul_emd_distance_test};


pub trait NodeTrait{
    fn cul_distance(&self, centroid: WinDistCenterPtr) -> Result<f64, String> ;           //计算距离
    fn cul_distance_node(&self, node: &WinDistNodePtr) -> Result<f64, String>;           
}

pub trait CenterTrait{
    fn update_centorid(& mut self) -> Result<(), String> ;   //更新类中心
    fn has_diff(&self) -> Result<bool, String>;  //与上个类中心是否有diff
}

impl NodeTrait for WinDistNode {
    fn cul_distance(&self, centroid: WinDistCenterPtr) -> Result<f64, String> {
        let b_centroid = centroid.lock().unwrap(); //可不可以使用生命周期解决？
        let c_dist = b_centroid.get_rwdist();
        let out = cul_emd_distance_test(self.get_rwdist(), c_dist);
        Ok(out)
    }

    fn cul_distance_node(&self, node: &WinDistNodePtr) -> Result<f64, String> {
        //let c_dist = node.get_rwdist();
        let out = cul_emd_distance_test(self.get_rwdist(), node.get_rwdist());
        Ok(out)
    }
}

impl CenterTrait for WinDistCenter{
    fn update_centorid(& mut self) -> Result<(), String> {
        let len = self.point_set.len();
        let mut new_centroid_dist = [0.0; 3];
        let mut weights = 0;
        self.point_set.iter().for_each(|p|{
            let mut dist = p.get_rwdist().win_dist;
            for v in dist.iter_mut(){
                *v *= p.origin_count;
            }
            //new_centroid_dist += dist;
            //new_centroid_dist += p.get_rwdist().win_dist * p.origin_count;
            for (i ,v) in dist.iter().enumerate() {
                new_centroid_dist[i] += (*v as f64);
            }
            weights += p.origin_count;
        });
        for v in new_centroid_dist.iter_mut(){
            *v /= (weights as f64);
        }
        //new_centroid_dist /= weights;
        self.centroid = Arc::new(WinDistNode::new(-1, new_centroid_dist.iter().map(|&x| x as i64).collect::<Vec<i64>>().try_into().unwrap(), 1));
        //for i in 0..len{
        //    let p = self.point_set
        //}
        /*
        let mut distance_count = vec![0.0; len];
        for i in 0..len{
            let d1 = self.point_set.get(i).unwrap();
            for j in i+1..len{
                let d2 = self.point_set.get(j).unwrap();
                let dist = d1.cul_distance_node(d2).unwrap();
                distance_count[i] += dist;
                distance_count[j] += dist;
            }
        }

        let (min_index, _) = distance_count.iter().enumerate()
        .min_by(|(_, &a), (_, &b)| a.partial_cmp(&b).unwrap())
        .unwrap();
        
        let new_centroid = self.point_set.get(min_index).unwrap().clone();
        println!("index:{:?} - point:{:?}", min_index, new_centroid);
        println!("distance{:?}", distance_count);
        if(self.centroid.win_dist.win_dist_id == new_centroid.win_dist.win_dist_id){
            self.centorid_diff = true;
        }else{
            self.centorid_diff = false;
        }
        self.centroid = new_centroid;
        */
        Ok(())
    }

    fn has_diff(&self) -> Result<bool, String> {
        Ok(self.centorid_diff) // 这块没写完吧，上面那个函数没有更新
    }
}