use crate::code::LdpcCode;

pub struct BitFlipDecoder<'a> {
    code: &'a LdpcCode,
}

impl<'a> BitFlipDecoder<'a> {
    pub fn new(code: &'a LdpcCode) -> Self {
        Self { code }
    }

    // TODO paraléliser (le calcul de chaque check-node)
    pub fn decode(&self, received: &[u8], max_iter: usize) -> Option<Vec<u8>> {
        let n = self.code.n;
        let m = self.code.h_matrix.rows;

        let mut curr_bits = received.to_vec();

        for iter in 0..max_iter {
            // Syndrome s = v * H^T
            let mut s = vec![0; m];
            let mut s_w = 0;

            for (cnid, cb) in self.code.tanner_graph.check.iter().enumerate() {
                let mut sum = 0;
                // Calcul des equation de parité
                for &bid in cb {
                    sum ^= curr_bits[bid];
                }
                s[cnid] = sum;

                // Equation non vérifiée
                if sum == 1 {
                    s_w += 1;
                }
            }

            // println!("poid syndome: {s_w}");
            // Aucune erreurs
            if s_w == 0 {
                return Some(curr_bits);
            }

            // Calcul du nombre d'équations fausses le bit fait partie
            let mut cpt = vec![0; n];
            let mut max_cpt = 0;

            for (cid, &sb) in s.iter().enumerate() {
                if sb == 1 {
                    for &bid in &self.code.tanner_graph.check[cid] {
                        cpt[bid] += 1;
                        if cpt[bid] > max_cpt {
                            max_cpt = cpt[bid];
                        }
                    }
                }
            }

            if max_cpt == 0 {
                break;
            }

            // Flip des bit qui causent le plus d'équations fausses
            for i in 0..n {
                if cpt[i] == max_cpt {
                    curr_bits[i] ^= 1; // Bit flip
                }
            }
            // Seuil de 3
            // if max_cpt >= 3 {
            //     for i in 0..n {
            //         if cpt[i] == max_cpt {
            //             curr_bits[i] ^= 1;
            //         }
            //     }
            // } else if max_cpt > 0 {
            //     if let Some(idx) = cpt.iter().position(|&x| x == max_cpt) {
            //         curr_bits[idx] ^= 1;
            //     }
            // } else {
            //     break;
            // }
        }
        None
    }
}
