//! Loading a formula into the solver.
use vec_mut_scan::VecMutScan;

use partial_ref::{partial, PartialRef};

use varisat_formula::Lit;
use varisat_internal_proof::{DeleteClauseProof, ProofStep};

use crate::{
    clause::{db, ClauseHeader, Tier},
    context::{parts::*, Context},
    proof,
    prop::{assignment, full_restart, Reason},
    state::SatState,
    unit_simplify::resurrect_unit,
    variables,
};

/// Adds a clause to the current formula.
///
/// The input uses user variable names.
///
/// Removes duplicated literals, ignores tautological clauses (eg. x v -x v y), handles empty
/// clauses and dispatches among unit, binary and long clauses.
pub fn load_clause<'a>(
    mut ctx: partial!(
        Context<'a>,
        mut AnalyzeConflictP,
        mut AssignmentP,
        mut AssumptionsP,
        mut BinaryClausesP,
        mut ClauseAllocP,
        mut ClauseDbP,
        mut ImplGraphP,
        mut ProofP<'a>,
        mut SolverStateP,
        mut TmpDataP,
        mut TmpFlagsP,
        mut TrailP,
        mut VariablesP,
        mut VsidsP,
        mut WatchlistsP,
    ),
    user_lits: &[Lit],
) {
    match ctx.part(SolverStateP).sat_state {
        SatState::Unsat => return,
        SatState::Sat => {
            ctx.part_mut(SolverStateP).sat_state = SatState::Unknown;
        }
        _ => {}
    }

    ctx.part_mut(SolverStateP).formula_is_empty = false;

    // Restart the search when the user adds new clauses.
    full_restart(ctx.borrow());

    // Convert the clause from user to solver literals.
    let (tmp_data, mut ctx_variables) = ctx.split_part_mut(TmpDataP);
    variables::solver_from_user_lits(ctx_variables.borrow(), &mut tmp_data.lits, user_lits, true);

    let (tmp_data, mut ctx) = ctx.split_part_mut(TmpDataP);

    let lits = &mut tmp_data.lits;
    let false_lits = &mut tmp_data.lits_2;

    lits.sort_unstable();
    lits.dedup();

    proof::add_clause(ctx.borrow(), &lits);

    // Detect tautological clauses
    let mut last = None;

    for &lit in lits.iter() {
        if last == Some(!lit) {
            return;
        }
        last = Some(lit);
    }

    // If we're not a unit clause the contained variables are not isolated anymore.
    if lits.len() > 1 {
        for &lit in lits.iter() {
            ctx.part_mut(VariablesP)
                .var_data_solver_mut(lit.var())
                .isolated = false;
        }
    }

    // Remove satisfied clauses and handle false literals.
    //
    // Proof generation expects us to start with the actual input clauses. If we would remove false
    // literals we would have to generate proof steps for that. This would result in derived clauses
    // being added during loading. If we're running proof processors on the fly, they'd see those
    // derived clauses interspersed with the input clauses.
    //
    // We don't want to require each proof processor to handle dervied clause additions during
    // loading of the initial formula. Thus we need to handle clauses with false literals here.
    false_lits.clear();

    let mut lits_scan = VecMutScan::new(lits);

    let mut clause_is_true = false;

    // We move unassigned literals to the beginning to make sure we're going to watch unassigned
    // literals.
    while let Some(lit) = lits_scan.next() {
        match ctx.part(AssignmentP).lit_value(*lit) {
            Some(true) => {
                clause_is_true = true;
                break;
            }
            Some(false) => {
                false_lits.push(lit.remove());
            }
            None => (),
        }
    }

    drop(lits_scan);

    let will_conflict = lits.is_empty();

    // We resurrect any removed false literals to ensure propagation by this new clause. This is
    // also required to eventually simplify this clause.
    for &lit in false_lits.iter() {
        resurrect_unit(ctx.borrow(), !lit);
    }

    lits.extend_from_slice(&false_lits);

    if clause_is_true {
        if lits.len() > 1 {
            proof::add_step(
                ctx.borrow(),
                true,
                &ProofStep::DeleteClause {
                    clause: lits,
                    proof: DeleteClauseProof::Satisfied,
                },
            );
        }
        return;
    }

    match lits[..] {
        [] => ctx.part_mut(SolverStateP).sat_state = SatState::Unsat,
        [lit] => {
            if will_conflict {
                ctx.part_mut(SolverStateP).sat_state = SatState::Unsat
            } else {
                assignment::enqueue_assignment(ctx.borrow(), lit, Reason::Unit)
            }
        }
        [lit_0, lit_1] => {
            ctx.part_mut(BinaryClausesP)
                .add_binary_clause([lit_0, lit_1]);
        }
        _ => {
            let mut header = ClauseHeader::new();
            header.set_tier(Tier::Irred);

            db::add_clause(ctx.borrow(), header, lits);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    use partial_ref::IntoPartialRefMut;

    use varisat_formula::lits;

    use crate::clause::Tier;

    #[test]
    fn unsat_on_empty_clause() {
        let mut ctx = Context::default();
        let mut ctx = ctx.into_partial_ref_mut();

        load_clause(ctx.borrow(), &[]);

        assert_eq!(ctx.part(SolverStateP).sat_state, SatState::Unsat);
    }

    #[test]
    fn unit_clauses() {
        let mut ctx = Context::default();
        let mut ctx = ctx.into_partial_ref_mut();

        load_clause(ctx.borrow(), &lits![1]);

        assert_eq!(ctx.part(TrailP).trail().len(), 1);

        load_clause(ctx.borrow(), &lits![3, -3]);

        assert_eq!(ctx.part(TrailP).trail().len(), 1);

        load_clause(ctx.borrow(), &lits![-2]);

        assert_eq!(ctx.part(TrailP).trail().len(), 2);

        load_clause(ctx.borrow(), &lits![1, 1]);

        assert_eq!(ctx.part(TrailP).trail().len(), 2);

        assert_eq!(ctx.part(SolverStateP).sat_state, SatState::Unknown);

        load_clause(ctx.borrow(), &lits![2]);

        assert_eq!(ctx.part(TrailP).trail().len(), 2);

        assert_eq!(ctx.part(SolverStateP).sat_state, SatState::Unsat);
    }

    #[test]
    fn binary_clauses() {
        let mut ctx = Context::default();
        let mut ctx = ctx.into_partial_ref_mut();

        load_clause(ctx.borrow(), &lits![1, 2]);

        assert_eq!(ctx.part(BinaryClausesP).count(), 1);

        load_clause(ctx.borrow(), &lits![-1, 3, 3]);

        assert_eq!(ctx.part(BinaryClausesP).count(), 2);

        load_clause(ctx.borrow(), &lits![4, -4]);

        assert_eq!(ctx.part(BinaryClausesP).count(), 2);

        assert_eq!(ctx.part(SolverStateP).sat_state, SatState::Unknown);
    }

    #[test]
    fn long_clauses() {
        let mut ctx = Context::default();
        let mut ctx = ctx.into_partial_ref_mut();

        load_clause(ctx.borrow(), &lits![1, 2, 3]);

        assert_eq!(ctx.part(ClauseDbP).count_by_tier(Tier::Irred), 1);

        load_clause(ctx.borrow(), &lits![-2, 3, 3, 4]);

        assert_eq!(ctx.part(ClauseDbP).count_by_tier(Tier::Irred), 2);

        load_clause(ctx.borrow(), &lits![4, -5, 5, 2]);

        assert_eq!(ctx.part(ClauseDbP).count_by_tier(Tier::Irred), 2);

        assert_eq!(ctx.part(SolverStateP).sat_state, SatState::Unknown);
    }
}
