use std::ffi::CString;
use std::fs;
use std::path::Path;
use std::sync::Arc;

use rustc_data_structures::memmap::Mmap;
use rustc_errors::DiagCtxtHandle;
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo, SymbolExportLevel};
use rustc_middle::ty::TyCtxt;
use rustc_session::config::Lto;
use rustc_structures::CrateType;
use tracing::info;

use crate::back::symbol_export::{self, allocator_shim_symbols, symbol_name_for_instance_in_crate};
use crate::back::write::CodegenContext;
use crate::base::allocator_kind_for_codegen;
use crate::diagnostics::{DynamicLinkingWithLTO, LtoDisallowed, LtoDylib, LtoProcMacro};
use crate::traits::*;

pub struct ThinModule<B: WriteBackendMethods> {
    pub shared: Arc<ThinShared<B>>,
    pub idx: usize,
}

impl<B: WriteBackendMethods> ThinModule<B> {
    pub fn name(&self) -> &str {
        self.shared.module_names[self.idx].to_str().unwrap()
    }

    pub fn cost(&self) -> u64 {
        // Yes, that's correct, we're using the size of the bytecode as an
        // indicator for how costly this codegen unit is.
        self.data().len() as u64
    }

    pub fn data(&self) -> &[u8] {
        self.shared.modules[self.idx].data()
    }
}

pub struct ThinShared<B: WriteBackendMethods> {
    pub data: B::ThinData,
    pub modules: Vec<SerializedModule<B::ModuleBuffer>>,
    pub module_names: Vec<CString>,
}

pub enum SerializedModule<M: ModuleBufferMethods> {
    Local(M),
    FromRlib(Vec<u8>),
    FromUncompressedFile(Mmap),
}

impl<M: ModuleBufferMethods> SerializedModule<M> {
    pub fn from_file(bc_path: &Path) -> Self {
        let file = fs::File::open(&bc_path).unwrap_or_else(|e| {
            panic!("failed to open LTO bitcode file `{}`: {}", bc_path.display(), e)
        });

        let mmap = unsafe {
            Mmap::map(file).unwrap_or_else(|e| {
                panic!("failed to mmap LTO bitcode file `{}`: {}", bc_path.display(), e)
            })
        };
        SerializedModule::FromUncompressedFile(mmap)
    }

    pub fn data(&self) -> &[u8] {
        match *self {
            SerializedModule::Local(ref m) => m.data(),
            SerializedModule::FromRlib(ref m) => m,
            SerializedModule::FromUncompressedFile(ref m) => m,
        }
    }
}

fn crate_type_allows_lto(crate_type: CrateType) -> bool {
    match crate_type {
        CrateType::Executable
        | CrateType::Dylib
        | CrateType::StaticLib
        | CrateType::Cdylib
        | CrateType::ProcMacro
        | CrateType::Sdylib => true,
        CrateType::Rlib => false,
    }
}

pub(crate) fn exported_symbols_for_lto(
    tcx: TyCtxt<'_>,
    each_linked_rlib_for_lto: &[CrateNum],
) -> Vec<String> {
    let export_threshold = match tcx.sess.lto() {
        // We're just doing LTO for our one crate
        Lto::ThinLocal => SymbolExportLevel::Rust,

        // We're doing LTO for the entire crate graph
        Lto::Fat | Lto::Thin => symbol_export::crates_export_threshold(&tcx.crate_types()),

        Lto::No => return vec![],
    };

    let copy_symbols = |cnum| {
        tcx.exported_non_generic_symbols(cnum)
            .iter()
            .chain(tcx.exported_generic_symbols(cnum))
            .filter_map(|&(s, info): &(ExportedSymbol<'_>, SymbolExportInfo)| {
                if info.level.is_below_threshold(export_threshold) || info.used {
                    Some(symbol_name_for_instance_in_crate(tcx, s, cnum))
                } else {
                    None
                }
            })
            .collect::<Vec<_>>()
    };
    let mut symbols_below_threshold = {
        let _timer = tcx.prof.generic_activity("lto_generate_symbols_below_threshold");
        copy_symbols(LOCAL_CRATE)
    };
    info!("{} symbols to preserve in this crate", symbols_below_threshold.len());

    // If we're performing LTO for the entire crate graph, then for each of our
    // upstream dependencies, include their exported symbols.
    for &cnum in each_linked_rlib_for_lto {
        let _timer = tcx.prof.generic_activity("lto_generate_symbols_below_threshold");
        symbols_below_threshold.extend(copy_symbols(cnum));
    }

    // Mark allocator shim symbols as exported only if they were generated.
    if export_threshold == SymbolExportLevel::Rust
        && let Some(kind) = allocator_kind_for_codegen(tcx)
    {
        symbols_below_threshold.extend(allocator_shim_symbols(tcx, kind).map(|(name, _kind)| name));
    }

    symbols_below_threshold
}

pub(super) fn check_lto_allowed(cgcx: &CodegenContext, dcx: DiagCtxtHandle<'_>) {
    if cgcx.lto == Lto::ThinLocal {
        // Crate local LTO is always allowed
        return;
    }

    // Make sure we actually can run LTO
    for crate_type in cgcx.crate_types.iter() {
        if !crate_type_allows_lto(*crate_type) {
            dcx.handle().emit_fatal(LtoDisallowed);
        } else if *crate_type == CrateType::Dylib {
            if !cgcx.dylib_lto {
                dcx.handle().emit_fatal(LtoDylib);
            }
        } else if *crate_type == CrateType::ProcMacro && !cgcx.dylib_lto {
            dcx.handle().emit_fatal(LtoProcMacro);
        }
    }

    if cgcx.prefer_dynamic && !cgcx.dylib_lto {
        dcx.handle().emit_fatal(DynamicLinkingWithLTO);
    }
}
