use std::mem;

use rustc_index::IndexVec;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::{bug, span_bug};
use smallvec::{SmallVec, smallvec};
use tracing::debug;

use super::{
    Init, InitIndex, InitKind, InitLocation, LocationMap, LookupResult, MoveData, MoveOut,
    MoveOutIndex, MovePath, MovePathIndex, MovePathLookup, MoveSubPath, MoveSubPathResult,
};

struct MoveDataBuilder<'a, 'tcx, F> {
    body: &'a Body<'tcx>,
    loc: Location,
    tcx: TyCtxt<'tcx>,
    data: MoveData<'tcx>,
    filter: F,
}

impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
    fn new(body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, filter: F) -> Self {
        let mut move_paths = IndexVec::new();
        let mut move_out_path_map = IndexVec::new();
        let mut init_path_map = IndexVec::new();

        let locals = body
            .local_decls
            .iter_enumerated()
            .map(|(i, l)| {
                if l.is_deref_temp() {
                    return None;
                }
                if filter(l.ty) {
                    Some(new_move_path(
                        &mut move_paths,
                        &mut move_out_path_map,
                        &mut init_path_map,
                        None,
                        Place::from(i),
                    ))
                } else {
                    None
                }
            })
            .collect();

        MoveDataBuilder {
            body,
            loc: Location::START,
            tcx,
            data: MoveData {
                move_outs: IndexVec::new(),
                move_out_loc_map: LocationMap::new(body),
                rev_lookup: MovePathLookup {
                    locals,
                    projections: Default::default(),
                    un_derefer: Default::default(),
                },
                move_paths,
                move_out_path_map,
                inits: IndexVec::new(),
                init_loc_map: LocationMap::new(body),
                init_path_map,
            },
            filter,
        }
    }
}

fn new_move_path<'tcx>(
    move_paths: &mut IndexVec<MovePathIndex, MovePath<'tcx>>,
    move_out_path_map: &mut IndexVec<MovePathIndex, SmallVec<[MoveOutIndex; 4]>>,
    init_path_map: &mut IndexVec<MovePathIndex, SmallVec<[InitIndex; 4]>>,
    parent: Option<MovePathIndex>,
    place: Place<'tcx>,
) -> MovePathIndex {
    let move_path =
        move_paths.push(MovePath { next_sibling: None, first_child: None, parent, place });

    if let Some(parent) = parent {
        let next_sibling = mem::replace(&mut move_paths[parent].first_child, Some(move_path));
        move_paths[move_path].next_sibling = next_sibling;
    }

    let path_map_ent = move_out_path_map.push(smallvec![]);
    assert_eq!(path_map_ent, move_path);

    let init_path_map_ent = init_path_map.push(smallvec![]);
    assert_eq!(init_path_map_ent, move_path);

    move_path
}

impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
    /// This creates a MovePath for a given place, calling `on_move`
    /// if it can be moved from. If theres a union in the path, its
    /// move place will be given to `on_move`. If there's a subslice
    /// projection, `on_move` will be called for each element.
    ///
    /// NOTE: places behind references *do not* get a move path, which is
    /// problematic for borrowck.
    ///
    /// Maybe we should have separate "borrowck" and "moveck" modes.
    fn move_path_for<G>(&mut self, place: Place<'tcx>, mut on_move: G)
    where
        G: FnMut(&mut Self, MovePathIndex),
    {
        let data = &mut self.data;

        debug!("lookup({:?})", place);
        let Some(mut base) = data.rev_lookup.find_local(place.local) else {
            return;
        };

        // The move path index of the first union that we find. Once this is
        // some we stop creating child move paths, since moves from unions
        // move the whole thing.
        // We continue looking for other move errors though so that moving
        // from `*(u.f: &_)` isn't allowed.
        let mut union_path = None;

        let mut iter = data.rev_lookup.un_derefer.iter_projections(place.as_ref());
        while let Some((place_ref, elem)) = iter.next() {
            let body = self.body;
            let tcx = self.tcx;
            let place_ty = place_ref.ty(body, tcx).ty;
            if place_ty.references_error() {
                return;
            }

            let res = MoveSubPath::of(elem.kind());

            let move_elem = match res {
                MoveSubPathResult::One(move_elem) => {
                    match move_elem {
                        MoveSubPath::Deref => match place_ty.kind() {
                            ty::Ref(..) | ty::RawPtr(..) => {
                                return;
                            }
                            ty::Adt(adt, _) => {
                                if !adt.is_box() {
                                    bug!("Adt should be a box type when Place is deref");
                                }
                            }
                            ty::Bool
                            | ty::Char
                            | ty::Int(_)
                            | ty::Uint(_)
                            | ty::Float(_)
                            | ty::Foreign(_)
                            | ty::Str
                            | ty::Array(_, _)
                            | ty::Pat(_, _)
                            | ty::Slice(_)
                            | ty::FnDef(_, _)
                            | ty::FnPtr(..)
                            | ty::Dynamic(_, _)
                            | ty::Closure(..)
                            | ty::CoroutineClosure(..)
                            | ty::Coroutine(_, _)
                            | ty::CoroutineWitness(..)
                            | ty::Never
                            | ty::Tuple(_)
                            | ty::UnsafeBinder(_)
                            | ty::Alias(_, _)
                            | ty::Param(_)
                            | ty::Bound(_, _)
                            | ty::Infer(_)
                            | ty::Error(_)
                            | ty::Placeholder(_) => {
                                bug!("When Place is Deref it's type shouldn't be {place_ty:#?}")
                            }
                        },
                        MoveSubPath::Field(_) => match place_ty.kind() {
                            ty::Adt(adt, _) => {
                                if adt.has_dtor(tcx) {
                                    return;
                                }
                                if adt.is_union() {
                                    union_path.get_or_insert(base);
                                }
                            }
                            ty::Closure(..)
                            | ty::CoroutineClosure(..)
                            | ty::Coroutine(_, _)
                            | ty::Tuple(_) => (),
                            ty::Bool
                            | ty::Char
                            | ty::Int(_)
                            | ty::Uint(_)
                            | ty::Float(_)
                            | ty::Foreign(_)
                            | ty::Str
                            | ty::Array(_, _)
                            | ty::Pat(_, _)
                            | ty::Slice(_)
                            | ty::RawPtr(_, _)
                            | ty::Ref(_, _, _)
                            | ty::FnDef(_, _)
                            | ty::FnPtr(..)
                            | ty::Dynamic(_, _)
                            | ty::CoroutineWitness(..)
                            | ty::Never
                            | ty::UnsafeBinder(_)
                            | ty::Alias(_, _)
                            | ty::Param(_)
                            | ty::Bound(_, _)
                            | ty::Infer(_)
                            | ty::Error(_)
                            | ty::Placeholder(_) => bug!(
                                "When Place contains ProjectionElem::Field its type shouldn't be {place_ty:#?}"
                            ),
                        },
                        MoveSubPath::ConstantIndex(_) => match place_ty.kind() {
                            ty::Slice(_) => {
                                return;
                            }
                            ty::Array(_, _) => (),
                            _ => bug!("Unexpected type {:#?}", place_ty.is_array()),
                        },
                        MoveSubPath::Downcast(_) => (),
                        MoveSubPath::UnwrapUnsafeBinder => (),
                    };

                    move_elem
                }

                // Split `Subslice` patterns into the corresponding list of
                // `ConstIndex` patterns. This is done to ensure that all move paths
                // are disjoint, which is expected by drop elaboration.
                MoveSubPathResult::Subslice { from, to } => {
                    assert!(
                        iter.all(
                            |(_, elem)| MoveSubPath::of(elem.kind()) == MoveSubPathResult::Skip
                        )
                    );
                    drop(iter); // drop for borrowck

                    let (&elem_ty, len) = match place_ty.kind() {
                        ty::Array(ty, size) => (
                            ty,
                            size.try_to_target_usize(self.tcx)
                                .expect("expected subslice projection on fixed-size array"),
                        ),
                        _ => bug!("from_end: false slice pattern of non-array type"),
                    };

                    if !(self.filter)(elem_ty) {
                        return;
                    }

                    for offset in from..to {
                        let place_elem =
                            PlaceElem::ConstantIndex { offset, min_length: len, from_end: false };
                        let subpath_elem = MoveSubPath::ConstantIndex(offset);

                        let mpi = self.add_move_path(base, subpath_elem, |tcx| {
                            place_ref.project_deeper(&[place_elem], tcx)
                        });
                        on_move(self, mpi);
                    }

                    return;
                }

                MoveSubPathResult::Skip => continue,
                MoveSubPathResult::Stop => return,
            };

            let elem_ty = PlaceTy::from_ty(place_ty).projection_ty(tcx, elem).ty;
            if !(self.filter)(elem_ty) {
                return;
            }
            if union_path.is_none() {
                // inlined from add_move_path because of a borrowck conflict with the iterator
                base = *data.rev_lookup.projections.entry((base, move_elem)).or_insert_with(|| {
                    new_move_path(
                        &mut data.move_paths,
                        &mut data.move_out_path_map,
                        &mut data.init_path_map,
                        Some(base),
                        place_ref.project_deeper(&[elem], tcx),
                    )
                })
            }
        }

        drop(iter); // drop for borrowck

        if let Some(base) = union_path {
            // Move out of union - always move the entire union.
            on_move(self, base);
        } else {
            on_move(self, base);
        }
    }

    fn add_move_path(
        &mut self,
        base: MovePathIndex,
        elem: MoveSubPath,
        mk_place: impl FnOnce(TyCtxt<'tcx>) -> Place<'tcx>,
    ) -> MovePathIndex {
        let MoveDataBuilder {
            data: MoveData { rev_lookup, move_paths, move_out_path_map, init_path_map, .. },
            tcx,
            ..
        } = self;
        *rev_lookup.projections.entry((base, elem)).or_insert_with(move || {
            new_move_path(move_paths, move_out_path_map, init_path_map, Some(base), mk_place(*tcx))
        })
    }

    fn create_move_path(&mut self, place: Place<'tcx>) {
        // This is an non-moving access (such as an overwrite or
        // drop), so this not being a valid move path is OK.
        self.move_path_for(place, |_, _| ());
    }

    fn finalize(self) -> MoveData<'tcx> {
        debug!("{}", {
            debug!("moves for {:?}:", self.body.span);
            for (j, mo) in self.data.move_outs.iter_enumerated() {
                debug!("    {:?} = {:?}", j, mo);
            }
            debug!("move paths for {:?}:", self.body.span);
            for (j, path) in self.data.move_paths.iter_enumerated() {
                debug!("    {:?} = {:?}", j, path);
            }
            "done dumping moves"
        });

        self.data
    }
}

pub(super) fn gather_moves<'tcx>(
    body: &Body<'tcx>,
    tcx: TyCtxt<'tcx>,
    filter: impl Fn(Ty<'tcx>) -> bool,
) -> MoveData<'tcx> {
    let mut builder = MoveDataBuilder::new(body, tcx, filter);

    builder.gather_args();

    for (bb, block) in body.basic_blocks.iter_enumerated() {
        for (i, stmt) in block.statements.iter().enumerate() {
            builder.loc = Location { block: bb, statement_index: i };
            builder.gather_statement(stmt);
        }

        builder.loc = Location { block: bb, statement_index: block.statements.len() };
        builder.gather_terminator(block.terminator());
    }

    builder.finalize()
}

impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
    fn gather_args(&mut self) {
        for arg in self.body.args_iter() {
            if let Some(path) = self.data.rev_lookup.find_local(arg) {
                let init = self.data.inits.push(Init {
                    path,
                    kind: InitKind::Deep,
                    location: InitLocation::Argument(arg),
                });

                debug!("gather_args: adding init {:?} of {:?} for argument {:?}", init, path, arg);

                self.data.init_path_map[path].push(init);
            }
        }
    }

    fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
        debug!("gather_statement({:?}, {:?})", self.loc, stmt);
        match &stmt.kind {
            StatementKind::Assign((place, Rvalue::CopyForDeref(reffed))) => {
                let local = place.as_local().unwrap();
                assert!(self.body.local_decls[local].is_deref_temp());

                let rev_lookup = &mut self.data.rev_lookup;

                rev_lookup.un_derefer.insert(local, reffed.as_ref());
                let base_local = rev_lookup.un_derefer.deref_chain(local).first().unwrap().local;
                rev_lookup.locals[local] = rev_lookup.locals[base_local];
            }
            StatementKind::Assign((place, rval)) => {
                self.create_move_path(*place);
                self.gather_init(place.as_ref(), InitKind::Deep);
                self.gather_rvalue(rval);
            }
            StatementKind::FakeRead((_, place)) => {
                self.create_move_path(*place);
            }
            StatementKind::StorageLive(_) => {}
            StatementKind::StorageDead(local) => {
                // DerefTemp locals (results of CopyForDeref) don't actually move anything.
                if !self.body.local_decls[*local].is_deref_temp() {
                    self.gather_move(Place::from(*local));
                }
            }
            StatementKind::SetDiscriminant { .. } => {
                span_bug!(
                    stmt.source_info.span,
                    "SetDiscriminant/Deinit should not exist during borrowck"
                );
            }
            StatementKind::AscribeUserType(..)
            | StatementKind::PlaceMention(..)
            | StatementKind::Coverage(..)
            | StatementKind::Intrinsic(..)
            | StatementKind::ConstEvalCounter
            | StatementKind::BackwardIncompatibleDropHint { .. }
            | StatementKind::Nop => {}
        }
    }

    fn gather_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
        match *rvalue {
            Rvalue::ThreadLocalRef(_) => {} // not-a-move
            Rvalue::Use(ref operand, _)
            | Rvalue::Repeat(ref operand, _)
            | Rvalue::Cast(_, ref operand, _)
            | Rvalue::UnaryOp(_, ref operand)
            | Rvalue::WrapUnsafeBinder(ref operand, _) => self.gather_operand(operand),
            Rvalue::BinaryOp(ref _binop, (ref lhs, ref rhs)) => {
                self.gather_operand(lhs);
                self.gather_operand(rhs);
            }
            Rvalue::Aggregate(ref _kind, ref operands) => {
                for operand in operands {
                    self.gather_operand(operand);
                }
            }
            Rvalue::CopyForDeref(..) => unreachable!(),
            Rvalue::Ref(..)
            | Rvalue::Reborrow(..)
            | Rvalue::RawPtr(..)
            | Rvalue::Discriminant(..) => {}
        }
    }

    fn gather_terminator(&mut self, term: &Terminator<'tcx>) {
        debug!("gather_terminator({:?}, {:?})", self.loc, term);
        match term.kind {
            TerminatorKind::Goto { target: _ }
            | TerminatorKind::FalseEdge { .. }
            | TerminatorKind::FalseUnwind { .. } => {}
            // In some sense returning moves the return place into the current
            // call's destination, however, since there are no statements after
            // this that could possibly access the return place, this doesn't
            // need recording.
            TerminatorKind::Return
            | TerminatorKind::UnwindResume
            | TerminatorKind::UnwindTerminate(_)
            | TerminatorKind::CoroutineDrop
            | TerminatorKind::Unreachable
            | TerminatorKind::Drop { .. } => {}

            TerminatorKind::Assert { ref cond, .. } => {
                self.gather_operand(cond);
            }

            TerminatorKind::SwitchInt { ref discr, .. } => {
                self.gather_operand(discr);
            }

            TerminatorKind::Yield { ref value, resume_arg: place, .. } => {
                self.gather_operand(value);
                self.create_move_path(place);
                self.gather_init(place.as_ref(), InitKind::Deep);
            }
            TerminatorKind::Call {
                ref func,
                ref args,
                destination,
                target,
                unwind: _,
                call_source: _,
                fn_span: _,
            } => {
                self.gather_operand(func);
                for arg in args {
                    self.gather_operand(&arg.node);
                }
                if let Some(_bb) = target {
                    self.create_move_path(destination);
                    self.gather_init(destination.as_ref(), InitKind::NonPanicPathOnly);
                }
            }
            TerminatorKind::TailCall { ref func, ref args, .. } => {
                self.gather_operand(func);
                for arg in args {
                    self.gather_operand(&arg.node);
                }
            }
            TerminatorKind::InlineAsm {
                asm_macro: _,
                template: _,
                ref operands,
                options: _,
                line_spans: _,
                targets: _,
                unwind: _,
            } => {
                for op in operands {
                    match *op {
                        InlineAsmOperand::In { reg: _, ref value } => {
                            self.gather_operand(value);
                        }
                        InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
                            if let Some(place) = place {
                                self.create_move_path(place);
                                self.gather_init(place.as_ref(), InitKind::Deep);
                            }
                        }
                        InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
                            self.gather_operand(in_value);
                            if let Some(out_place) = out_place {
                                self.create_move_path(out_place);
                                self.gather_init(out_place.as_ref(), InitKind::Deep);
                            }
                        }
                        InlineAsmOperand::Const { value: _ }
                        | InlineAsmOperand::SymFn { value: _ }
                        | InlineAsmOperand::SymStatic { def_id: _ }
                        | InlineAsmOperand::Label { target_index: _ } => {}
                    }
                }
            }
        }
    }

    fn gather_operand(&mut self, operand: &Operand<'tcx>) {
        match *operand {
            // not-a-move
            Operand::Constant(..) | Operand::Copy(..) | Operand::RuntimeChecks(_) => {}
            // a move
            Operand::Move(place) => {
                self.gather_move(place);
            }
        }
    }

    fn gather_move(&mut self, place: Place<'tcx>) {
        debug!("gather_move({:?}, {:?})", self.loc, place);
        self.move_path_for(place, |this, mpi| this.record_move(place, mpi));
    }

    fn record_move(&mut self, place: Place<'tcx>, path: MovePathIndex) {
        let move_out = self.data.move_outs.push(MoveOut { path, source: self.loc });
        debug!(
            "gather_move({:?}, {:?}): adding move {:?} of {:?}",
            self.loc, place, move_out, path
        );
        self.data.move_out_path_map[path].push(move_out);
        self.data.move_out_loc_map[self.loc].push(move_out);
    }

    fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) {
        debug!("gather_init({:?}, {:?})", self.loc, place);

        let mut place = place;

        // Check if we are assigning into a field of a union, if so, lookup the place
        // of the union so it is marked as initialized again.
        if let Some((place_base, ProjectionElem::Field(_, _))) = place.last_projection() {
            if place_base.ty(self.body, self.tcx).ty.is_union() {
                place = place_base;
            }
        }

        if let LookupResult::Exact(path) = self.data.rev_lookup.find(place) {
            let init = self.data.inits.push(Init {
                location: InitLocation::Statement(self.loc),
                path,
                kind,
            });

            debug!(
                "gather_init({:?}, {:?}): adding init {:?} of {:?}",
                self.loc, place, init, path
            );

            self.data.init_path_map[path].push(init);
            self.data.init_loc_map[self.loc].push(init);
        }
    }
}
