// This pass converts move out from array by Subslice and
// ConstIndex{.., from_end: true} to ConstIndex move out(s) from begin
// of array. It allows detect error by mir borrowck and elaborate
// drops for array without additional work.
//
// Example:
//
// let a = [ box 1,box 2, box 3];
// if b {
//  let [_a.., _] = a;
// } else {
//  let [.., _b] = a;
// }
//
//  mir statement _10 = move _2[:-1]; replaced by:
//  StorageLive(_12);
//  _12 = move _2[0 of 3];
//  StorageLive(_13);
//  _13 = move _2[1 of 3];
//  _10 = [move _12, move _13]
//  StorageDead(_12);
//  StorageDead(_13);
//
//  and mir statement _11 = move _2[-1 of 1]; replaced by:
//  _11 = move _2[2 of 3];
//
// FIXME: integrate this transformation to the mir build

use rustc::ty;
use rustc::ty::TyCtxt;
use rustc::mir::*;
use rustc::mir::visit::{Visitor, PlaceContext, NonUseContext};
use rustc_data_structures::indexed_vec::{IndexVec};
use crate::transform::{MirPass, MirSource};
use crate::util::patch::MirPatch;

pub struct UniformArrayMoveOut;

impl<'tcx> MirPass<'tcx> for UniformArrayMoveOut {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
        let mut patch = MirPatch::new(body);
        let param_env = tcx.param_env(src.def_id());
        {
            let mut visitor = UniformArrayMoveOutVisitor{body, patch: &mut patch, tcx, param_env};
            visitor.visit_body(body);
        }
        patch.apply(body);
    }
}

struct UniformArrayMoveOutVisitor<'a, 'tcx> {
    body: &'a Body<'tcx>,
    patch: &'a mut MirPatch<'tcx>,
    tcx: TyCtxt<'tcx>,
    param_env: ty::ParamEnv<'tcx>,
}

impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> {
    fn visit_assign(&mut self,
                    dst_place: &Place<'tcx>,
                    rvalue: &Rvalue<'tcx>,
                    location: Location) {
        if let Rvalue::Use(Operand::Move(ref src_place)) = rvalue {
            if let box [proj_base @ .., elem] = &src_place.projection {
                if let ProjectionElem::ConstantIndex{offset: _,
                                                     min_length: _,
                                                     from_end: false} = elem {
                    // no need to transformation
                } else {
                    let place_ty =
                        Place::ty_from(&src_place.base, proj_base, self.body, self.tcx).ty;
                    if let ty::Array(item_ty, const_size) = place_ty.sty {
                        if let Some(size) = const_size.try_eval_usize(self.tcx, self.param_env) {
                            assert!(size <= u32::max_value() as u64,
                                    "uniform array move out doesn't supported
                                     for array bigger then u32");
                            self.uniform(
                                location,
                                dst_place,
                                &src_place.base,
                                &src_place.projection,
                                item_ty,
                                size as u32,
                            );
                        }
                    }

                }
            }
        }
        self.super_assign(dst_place, rvalue, location)
    }
}

impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
    fn uniform(&mut self,
               location: Location,
               dst_place: &Place<'tcx>,
               base: &PlaceBase<'tcx>,
               proj: &[PlaceElem<'tcx>],
               item_ty: &'tcx ty::TyS<'tcx>,
               size: u32) {
        if let [proj_base @ .., elem] = proj {
            match elem {
                // uniforms statements like_10 = move _2[:-1];
                ProjectionElem::Subslice{from, to} => {
                    self.patch.make_nop(location);
                    let temps : Vec<_> = (*from..(size-*to)).map(|i| {
                        let temp =
                            self.patch.new_temp(item_ty, self.body.source_info(location).span);
                        self.patch.add_statement(location, StatementKind::StorageLive(temp));

                        let mut projection = proj_base.to_vec();
                        projection.push(ProjectionElem::ConstantIndex {
                            offset: i,
                            min_length: size,
                            from_end: false,
                        });
                        self.patch.add_assign(location,
                                              Place::from(temp),
                                              Rvalue::Use(
                                                  Operand::Move(
                                                      Place {
                                                          base: base.clone(),
                                                          projection: projection.into_boxed_slice(),
                                                      }
                                                  )
                                              )
                        );
                        temp
                    }).collect();
                    self.patch.add_assign(
                        location,
                        dst_place.clone(),
                        Rvalue::Aggregate(
                            box AggregateKind::Array(item_ty),
                            temps.iter().map(
                                |x| Operand::Move(Place::from(*x))
                            ).collect()
                        )
                    );
                    for temp in temps {
                        self.patch.add_statement(location, StatementKind::StorageDead(temp));
                    }
                }
                // uniforms statements like _11 = move _2[-1 of 1];
                ProjectionElem::ConstantIndex{offset, min_length: _, from_end: true} => {
                    self.patch.make_nop(location);

                    let mut projection = proj_base.to_vec();
                    projection.push(ProjectionElem::ConstantIndex {
                        offset: size - offset,
                        min_length: size,
                        from_end: false,
                    });
                    self.patch.add_assign(location,
                                          dst_place.clone(),
                                          Rvalue::Use(
                                              Operand::Move(
                                                  Place {
                                                      base: base.clone(),
                                                      projection: projection.into_boxed_slice(),
                                                  }
                                              )
                                          )
                    );
                }
                _ => {}
            }
        }
    }
}

// Restore Subslice move out after analysis
// Example:
//
//  next statements:
//   StorageLive(_12);
//   _12 = move _2[0 of 3];
//   StorageLive(_13);
//   _13 = move _2[1 of 3];
//   _10 = [move _12, move _13]
//   StorageDead(_12);
//   StorageDead(_13);
//
// replaced by _10 = move _2[:-1];

pub struct RestoreSubsliceArrayMoveOut;

impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) {
        let mut patch = MirPatch::new(body);
        let param_env = tcx.param_env(src.def_id());
        {
            let mut visitor = RestoreDataCollector {
                locals_use: IndexVec::from_elem(LocalUse::new(), &body.local_decls),
                candidates: vec![],
            };
            visitor.visit_body(body);

            for candidate in &visitor.candidates {
                let statement = &body[candidate.block].statements[candidate.statement_index];
                if let StatementKind::Assign(box(ref dst_place, ref rval)) = statement.kind {
                    if let Rvalue::Aggregate(box AggregateKind::Array(_), ref items) = *rval {
                        let items : Vec<_> = items.iter().map(|item| {
                            if let Operand::Move(Place {
                                base: PlaceBase::Local(local),
                                projection: box [],
                            }) = item {
                                let local_use = &visitor.locals_use[*local];
                                let opt_index_and_place =
                                    Self::try_get_item_source(local_use, body);
                                // each local should be used twice:
                                //  in assign and in aggregate statements
                                if local_use.use_count == 2 && opt_index_and_place.is_some() {
                                    let (index, src_place) = opt_index_and_place.unwrap();
                                    return Some((local_use, index, src_place));
                                }
                            }
                            None
                        }).collect();

                        let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2);
                        let opt_size = opt_src_place.and_then(|src_place| {
                            let src_ty =
                                Place::ty_from(src_place.base, src_place.projection, body, tcx).ty;
                            if let ty::Array(_, ref size_o) = src_ty.sty {
                                size_o.try_eval_usize(tcx, param_env)
                            } else {
                                None
                            }
                        });
                        Self::check_and_patch(*candidate, &items, opt_size, &mut patch, dst_place);
                    }
                }
            }
        }
        patch.apply(body);
    }
}

impl RestoreSubsliceArrayMoveOut {
    // Checks that source has size, all locals are inited from same source place and
    // indices is an integer interval. If all checks pass do the replacent.
    // items are Vec<Option<LocalUse, index in source array, source place for init local>>
    fn check_and_patch<'tcx>(candidate: Location,
                             items: &[Option<(&LocalUse, u32, PlaceRef<'_, 'tcx>)>],
                             opt_size: Option<u64>,
                             patch: &mut MirPatch<'tcx>,
                             dst_place: &Place<'tcx>) {
        let opt_src_place = items.first().and_then(|x| *x).map(|x| x.2);

        if opt_size.is_some() && items.iter().all(
            |l| l.is_some() && l.unwrap().2 == opt_src_place.unwrap()) {
            let src_place = opt_src_place.unwrap();

            let indices: Vec<_> = items.iter().map(|x| x.unwrap().1).collect();
            for i in 1..indices.len() {
                if indices[i - 1] + 1 != indices[i] {
                    return;
                }
            }

            let min = *indices.first().unwrap();
            let max = *indices.last().unwrap();

            for item in items {
                let locals_use = item.unwrap().0;
                patch.make_nop(locals_use.alive.unwrap());
                patch.make_nop(locals_use.dead.unwrap());
                patch.make_nop(locals_use.first_use.unwrap());
            }
            patch.make_nop(candidate);
            let size = opt_size.unwrap() as u32;

            let mut projection = src_place.projection.to_vec();
            projection.push(ProjectionElem::Subslice { from: min, to: size - max - 1 });
            patch.add_assign(
                candidate,
                dst_place.clone(),
                Rvalue::Use(Operand::Move(Place {
                    base: src_place.base.clone(),
                    projection: projection.into_boxed_slice(),
                })),
            );
        }
    }

    fn try_get_item_source<'a, 'tcx>(local_use: &LocalUse,
                                     body: &'a Body<'tcx>) -> Option<(u32, PlaceRef<'a, 'tcx>)> {
        if let Some(location) = local_use.first_use {
            let block = &body[location.block];
            if block.statements.len() > location.statement_index {
                let statement = &block.statements[location.statement_index];
                if let StatementKind::Assign(
                    box(
                        Place {
                            base: PlaceBase::Local(_),
                            projection: box [],
                        },
                        Rvalue::Use(Operand::Move(Place {
                            base: _,
                            projection: box [.., ProjectionElem::ConstantIndex {
                                offset, min_length: _, from_end: false
                            }],
                        })),
                    )
                ) = &statement.kind {
                    // FIXME remove once we can use slices patterns
                    if let StatementKind::Assign(
                        box(
                            _,
                            Rvalue::Use(Operand::Move(Place {
                                base,
                                projection: box [proj_base @ .., _],
                            })),
                        )
                    ) = &statement.kind {
                        return Some((*offset, PlaceRef {
                            base,
                            projection: proj_base,
                        }))
                    }
                }
            }
        }
        None
    }
}

#[derive(Copy, Clone, Debug)]
struct LocalUse {
    alive: Option<Location>,
    dead: Option<Location>,
    use_count: u32,
    first_use: Option<Location>,
}

impl LocalUse {
    pub fn new() -> Self {
        LocalUse{alive: None, dead: None, use_count: 0, first_use: None}
    }
}

struct RestoreDataCollector {
    locals_use: IndexVec<Local, LocalUse>,
    candidates: Vec<Location>,
}

impl<'tcx> Visitor<'tcx> for RestoreDataCollector {
    fn visit_assign(&mut self,
                    place: &Place<'tcx>,
                    rvalue: &Rvalue<'tcx>,
                    location: Location) {
        if let Rvalue::Aggregate(box AggregateKind::Array(_), _) = *rvalue {
            self.candidates.push(location);
        }
        self.super_assign(place, rvalue, location)
    }

    fn visit_local(&mut self,
                   local: &Local,
                   context: PlaceContext,
                   location: Location) {
        let local_use = &mut self.locals_use[*local];
        match context {
            PlaceContext::NonUse(NonUseContext::StorageLive) => local_use.alive = Some(location),
            PlaceContext::NonUse(NonUseContext::StorageDead) => local_use.dead = Some(location),
            _ => {
                local_use.use_count += 1;
                if local_use.first_use.is_none() {
                    local_use.first_use = Some(location);
                }
            }
        }
    }
}
