use std::marker;
use fixedbitset::FixedBitSet;

use super::{
    EdgeType,
    Incoming,
};
use super::graph::{
    Graph,
    IndexType,
    NodeIndex,
};

use super::visit::GetAdjacencyMatrix;

#[derive(Debug)]
struct Vf2State<Ty, Ix> {
    /// The current mapping M(s) of nodes from G0 → G1 and G1 → G0,
    /// NodeIndex::end() for no mapping.
    mapping: Vec<NodeIndex<Ix>>,
    /// out[i] is non-zero if i is in either M_0(s) or Tout_0(s)
    /// These are all the next vertices that are not mapped yet, but
    /// have an outgoing edge from the mapping.
    out: Vec<usize>,
    /// ins[i] is non-zero if i is in either M_0(s) or Tin_0(s)
    /// These are all the incoming vertices, those not mapped yet, but
    /// have an edge from them into the mapping.
    /// Unused if graph is undirected -- it's identical with out in that case.
    ins: Vec<usize>,
    out_size: usize,
    ins_size: usize,
    adjacency_matrix: FixedBitSet,
    generation: usize,
    _etype: marker::PhantomData<Ty>,
}

impl<Ty, Ix> Vf2State<Ty, Ix>
    where Ty: EdgeType,
          Ix: IndexType,
{
    pub fn new<N, E>(g: &Graph<N, E, Ty, Ix>) -> Self {
        let c0 = g.node_count();
        let mut state = Vf2State {
            mapping: Vec::with_capacity(c0),
            out: Vec::with_capacity(c0),
            ins: Vec::with_capacity(c0 * (g.is_directed() as usize)),
            out_size: 0,
            ins_size: 0,
            adjacency_matrix: g.adjacency_matrix(),
            generation: 0,
            _etype: marker::PhantomData,
        };
        for _ in 0..c0 {
            state.mapping.push(NodeIndex::end());
            state.out.push(0);
            if Ty::is_directed() {
                state.ins.push(0);
            }
        }
        state
    }

    /// Return **true** if we have a complete mapping
    pub fn is_complete(&self) -> bool {
        self.generation == self.mapping.len()
    }

    /// Add mapping **from** <-> **to** to the state.
    pub fn push_mapping<N, E>(&mut self, from: NodeIndex<Ix>, to: NodeIndex<Ix>,
                              g: &Graph<N, E, Ty, Ix>)
    {
        self.generation += 1;
        let s = self.generation;
        self.mapping[from.index()] = to;
        // update T0 & T1 ins/outs
        // T0out: Node in G0 not in M0 but successor of a node in M0.
        // st.out[0]: Node either in M0 or successor of M0
        for ix in g.neighbors(from) {
            if self.out[ix.index()] == 0 {
                self.out[ix.index()] = s;
                self.out_size += 1;
            }
        }
        if g.is_directed() {
            for ix in g.neighbors_directed(from, Incoming) {
                if self.ins[ix.index()] == 0 {
                    self.ins[ix.index()] = s;
                    self.ins_size += 1;
                }
            }
        }
    }

    /// Restore the state to before the last added mapping
    pub fn pop_mapping<N, E>(&mut self, from: NodeIndex<Ix>,
                             g: &Graph<N, E, Ty, Ix>)
    {
        let s = self.generation;
        self.generation -= 1;

        // undo (n, m) mapping
        self.mapping[from.index()] = NodeIndex::end();

        // unmark in ins and outs
        for ix in g.neighbors(from) {
            if self.out[ix.index()] == s {
                self.out[ix.index()] = 0;
                self.out_size -= 1;
            }
        }
        if g.is_directed() {
            for ix in g.neighbors_directed(from, Incoming) {
                if self.ins[ix.index()] == s {
                    self.ins[ix.index()] = 0;
                    self.ins_size -= 1;
                }
            }
        }
    }

    /// Find the next (least) node in the Tout set.
    pub fn next_out_index(&self, from_index: usize) -> Option<usize>
    {
        self.out[from_index..].iter()
                    .enumerate()
                    .filter(|&(index, elt)| *elt > 0 && self.mapping[from_index + index] == NodeIndex::end())
                    .next()
                    .map(|(index, _)| index)
    }

    /// Find the next (least) node in the Tin set.
    pub fn next_in_index(&self, from_index: usize) -> Option<usize>
    {
        if !Ty::is_directed() {
            return None
        }
        self.ins[from_index..].iter()
                    .enumerate()
                    .filter(|&(index, elt)| *elt > 0 && self.mapping[from_index + index] == NodeIndex::end())
                    .next()
                    .map(|(index, _)| index)
    }

    /// Find the next (least) node in the N - M set.
    pub fn next_rest_index(&self, from_index: usize) -> Option<usize>
    {
        self.mapping[from_index..].iter()
               .enumerate()
               .filter(|&(_, elt)| *elt == NodeIndex::end())
               .next()
               .map(|(index, _)| index)
    }
}


/// Return `true` if the graphs `g0` and `g1` are isomorphic.
///
/// Using the VF2 algorithm, only matching graph syntactically (graph
/// structure).
///
/// The graphs should not be multigraphs.
///
/// **Reference**
/// 
/// * Luigi P. Cordella, Pasquale Foggia, Carlo Sansone, Mario Vento;
///   *A (Sub)Graph Isomorphism Algorithm for Matching Large Graphs*
pub fn is_isomorphic<N, E, Ty, Ix>(g0: &Graph<N, E, Ty, Ix>,
                                   g1: &Graph<N, E, Ty, Ix>) -> bool
    where Ty: EdgeType,
          Ix: IndexType,
{
    if g0.node_count() != g1.node_count() || g0.edge_count() != g1.edge_count() {
        return false
    }

    let mut st = [Vf2State::new(g0), Vf2State::new(g1)];
    try_match(&mut st, g0, g1, &mut NoSemanticMatch, &mut NoSemanticMatch).unwrap_or(false)
}

/// Return `true` if the graphs `g0` and `g1` are isomorphic.
///
/// Using the VF2 algorithm, examining both syntactic and semantic
/// graph isomorphism (graph structure and matching node and edge weights).
///
/// The graphs should not be multigraphs.
pub fn is_isomorphic_matching<N, E, Ty, Ix, F, G>(g0: &Graph<N, E, Ty, Ix>,
                                                  g1: &Graph<N, E, Ty, Ix>,
                                                  mut node_match: F,
                                                  mut edge_match: G) -> bool
    where Ty: EdgeType,
          Ix: IndexType,
          F: FnMut(&N, &N) -> bool,
          G: FnMut(&E, &E) -> bool,
{
    if g0.node_count() != g1.node_count() || g0.edge_count() != g1.edge_count() {
        return false
    }

    let mut st = [Vf2State::new(g0), Vf2State::new(g1)];
    try_match(&mut st, g0, g1, &mut node_match, &mut edge_match).unwrap_or(false)
}

trait SemanticMatcher<T> {
    fn enabled() -> bool;
    fn eq(&mut self, &T, &T) -> bool;
}

struct NoSemanticMatch;

impl<T> SemanticMatcher<T> for NoSemanticMatch {
    #[inline]
    fn enabled() -> bool { false }
    #[inline]
    fn eq(&mut self, _: &T, _: &T) -> bool { true }
}

impl<T, F> SemanticMatcher<T> for F where F: FnMut(&T, &T) -> bool {
    #[inline]
    fn enabled() -> bool { true }
    #[inline]
    fn eq(&mut self, a: &T, b: &T) -> bool { self(a, b) }
}

/// Return Some(bool) if isomorphism is decided, else None.
fn try_match<N, E, Ty, Ix, F, G>(st: &mut [Vf2State<Ty, Ix>; 2],
                                 g0: &Graph<N, E, Ty, Ix>,
                                 g1: &Graph<N, E, Ty, Ix>,
                                 node_match: &mut F,
                                 edge_match: &mut G)
    -> Option<bool>
    where Ty: EdgeType,
          Ix: IndexType,
          F: SemanticMatcher<N>,
          G: SemanticMatcher<E>,
{
    let g = [g0, g1];
    let graph_indices = 0..2;
    let end = NodeIndex::end();

    // if all are mapped -- we are done and have an iso
    if st[0].is_complete() {
        return Some(true)
    }

    // A "depth first" search of a valid mapping from graph 1 to graph 2

    // F(s, n, m) -- evaluate state s and add mapping n <-> m

    // Find least T1out node (in st.out[1] but not in M[1])
    #[derive(Copy, Clone, PartialEq, Debug)]
    enum OpenList {
        Out,
        In,
        Other,
    }
    let mut open_list = OpenList::Out;

    let mut to_index;
    let mut from_index = None;
    // Try the out list
    to_index = st[1].next_out_index(0);

    if to_index.is_some() {
        from_index = st[0].next_out_index(0);
        open_list = OpenList::Out;
    }

    // Try the in list
    if to_index.is_none() || from_index.is_none() {
        to_index = st[1].next_in_index(0);

        if to_index.is_some() {
            from_index = st[0].next_in_index(0);
            open_list = OpenList::In;
        }
    }

    // Try the other list -- disconnected graph
    if to_index.is_none() || from_index.is_none() {
        to_index = st[1].next_rest_index(0);
        if to_index.is_some() {
            from_index = st[0].next_rest_index(0);
            open_list = OpenList::Other;
        }
    }

    let (cand0, cand1) = match (from_index, to_index) {
        (Some(n), Some(m)) => (n, m),
        // No more candidates
        _ => return None,
    };

    let mut nx = NodeIndex::new(cand0);
    let mx = NodeIndex::new(cand1);

    let mut first = true;

    'candidates: loop {
        if !first {
            // Find the next node index to try on the `from` side of the mapping
            let start = nx.index() + 1;
            let cand0 = match open_list {
                OpenList::Out => st[0].next_out_index(start),
                OpenList::In => st[0].next_in_index(start),
                OpenList::Other => st[0].next_rest_index(start),
            }.map(|c| c + start); // compensate for start offset.
            nx = match cand0 {
                None => break, // no more candidates
                Some(ix) => NodeIndex::new(ix),
            };
            debug_assert!(nx.index() >= start);
        }
        first = false;

        let nodes = [nx, mx];

        // Check syntactic feasibility of mapping by ensuring adjacencies
        // of nx map to adjacencies of mx.
        //
        // nx == map to => mx
        //
        // R_succ
        //
        // Check that every neighbor of nx is mapped to a neighbor of mx,
        // then check the reverse, from mx to nx. Check that they have the same
        // count of edges.
        //
        // Note: We want to check the lookahead measures here if we can,
        // R_out: Equal for G0, G1: Card(Succ(G, n) ^ Tout); for both Succ and Pred
        // R_in: Same with Tin
        // R_new: Equal for G0, G1: Ñ n Pred(G, n); both Succ and Pred,
        //      Ñ is G0 - M - Tin - Tout
        // last attempt to add these did not speed up any of the testcases
        let mut succ_count = [0, 0];
        for j in graph_indices.clone() {
            for n_neigh in g[j].neighbors(nodes[j]) {
                succ_count[j] += 1;
                // handle the self loop case; it's not in the mapping (yet)
                let m_neigh = if nodes[j] != n_neigh {
                    st[j].mapping[n_neigh.index()]
                } else {
                    nodes[1 - j]
                };
                if m_neigh == end {
                    continue;
                }
                let has_edge = g[1-j].is_adjacent(&st[1-j].adjacency_matrix, nodes[1-j], m_neigh);
                if !has_edge {
                    continue 'candidates;
                }
            }
        }
        if succ_count[0] != succ_count[1] {
            continue 'candidates;
        }

        // R_pred
        if g[0].is_directed() {
            let mut pred_count = [0, 0];
            for j in graph_indices.clone() {
                for n_neigh in g[j].neighbors_directed(nodes[j], Incoming) {
                    pred_count[j] += 1;
                    // the self loop case is handled in outgoing
                    let m_neigh = st[j].mapping[n_neigh.index()];
                    if m_neigh == end {
                        continue;
                    }
                    let has_edge = g[1-j].is_adjacent(&st[1-j].adjacency_matrix, m_neigh, nodes[1-j]);
                    if !has_edge {
                        continue 'candidates;
                    }
                }
            }
            if pred_count[0] != pred_count[1] {
                continue 'candidates;
            }
        }

        // semantic feasibility: compare associated data for nodes
        if F::enabled() && !node_match.eq(&g[0][nodes[0]], &g[1][nodes[1]]) {
            continue 'candidates;
        }

        // semantic feasibility: compare associated data for edges
        if G::enabled() {
            // outgoing edges
            for j in graph_indices.clone() {
                let mut edges = g[j].neighbors(nodes[j]).detach();
                while let Some((n_edge, n_neigh)) = edges.next(&g[j]) {
                    // handle the self loop case; it's not in the mapping (yet)
                    let m_neigh = if nodes[j] != n_neigh {
                        st[j].mapping[n_neigh.index()]
                    } else {
                        nodes[1 - j]
                    };
                    if m_neigh == end {
                        continue;
                    }
                    match g[1-j].find_edge(nodes[1 - j], m_neigh) {
                        Some(m_edge) => {
                            if !edge_match.eq(&g[j][n_edge], &g[1-j][m_edge]) {
                                continue 'candidates;
                            }
                        }
                        None => unreachable!() // covered by syntactic check
                    }
                }
            }

            // incoming edges
            if g[0].is_directed() {
                for j in graph_indices.clone() {
                    let mut edges = g[j].neighbors_directed(nodes[j], Incoming).detach();
                    while let Some((n_edge, n_neigh)) = edges.next(&g[j]) {
                        // the self loop case is handled in outgoing
                        let m_neigh = st[j].mapping[n_neigh.index()];
                        if m_neigh == end {
                            continue;
                        }
                        match g[1-j].find_edge(m_neigh, nodes[1-j]) {
                            Some(m_edge) => {
                                if !edge_match.eq(&g[j][n_edge], &g[1-j][m_edge]) {
                                    continue 'candidates;
                                }
                            }
                            None => unreachable!() // covered by syntactic check
                        }
                    }
                }
            }
        }

        // Add mapping nx <-> mx to the state
        for j in graph_indices.clone() {
            st[j].push_mapping(nodes[j], nodes[1-j], g[j]);
        }

        // Check cardinalities of Tin, Tout sets
        if st[0].out_size == st[1].out_size &&
           st[0].ins_size == st[1].ins_size
        {

            // Recurse
            match try_match(st, g0, g1, node_match, edge_match) {
                None => {}
                result => return result,
            }
        }

        // Restore state.
        for j in graph_indices.clone() {
            st[j].pop_mapping(nodes[j], g[j]);
        }
    }
    None
}

