use crate::llvm;
use crate::llvm::{False, ObjectFile, mk_section_iter};
use crate::llvm::archive_ro::ArchiveRO;
use rustc::middle::cstore::MetadataLoader;
use rustc_target::spec::Target;

use rustc_data_structures::owning_ref::OwningRef;
use rustc_codegen_ssa::METADATA_FILENAME;

use std::path::Path;
use std::slice;
use rustc_fs_util::path_to_c_string;

pub use rustc_data_structures::sync::MetadataRef;

pub struct LlvmMetadataLoader;

impl MetadataLoader for LlvmMetadataLoader {
    fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<MetadataRef, String> {
        // Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
        // internally to read the file. We also avoid even using a memcpy by
        // just keeping the archive along while the metadata is in use.
        let archive = ArchiveRO::open(filename)
            .map(|ar| OwningRef::new(box ar))
            .map_err(|e| {
                debug!("llvm didn't like `{}`: {}", filename.display(), e);
                format!("failed to read rlib metadata in '{}': {}", filename.display(), e)
            })?;
        let buf: OwningRef<_, [u8]> = archive
            .try_map(|ar| {
                ar.iter()
                    .filter_map(|s| s.ok())
                    .find(|sect| sect.name() == Some(METADATA_FILENAME))
                    .map(|s| s.data())
                    .ok_or_else(|| {
                        debug!("didn't find '{}' in the archive", METADATA_FILENAME);
                        format!("failed to read rlib metadata: '{}'",
                                filename.display())
                    })
            })?;
        Ok(rustc_erase_owner!(buf))
    }

    fn get_dylib_metadata(&self,
                          target: &Target,
                          filename: &Path)
                          -> Result<MetadataRef, String> {
        unsafe {
            let buf = path_to_c_string(filename);
            let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr())
                .ok_or_else(|| format!("error reading library: '{}'", filename.display()))?;
            let of = ObjectFile::new(mb)
                .map(|of| OwningRef::new(box of))
                .ok_or_else(|| format!("provided path not an object file: '{}'",
                                       filename.display()))?;
            let buf = of.try_map(|of| search_meta_section(of, target, filename))?;
            Ok(rustc_erase_owner!(buf))
        }
    }
}

fn search_meta_section<'a>(of: &'a ObjectFile,
                           target: &Target,
                           filename: &Path)
                           -> Result<&'a [u8], String> {
    unsafe {
        let si = mk_section_iter(of.llof);
        while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
            let mut name_buf = None;
            let name_len = llvm::LLVMRustGetSectionName(si.llsi, &mut name_buf);
            let name = name_buf.map_or(
                String::new(), // We got a NULL ptr, ignore `name_len`.
                |buf| String::from_utf8(
                    slice::from_raw_parts(buf.as_ptr() as *const u8,
                                          name_len as usize)
                    .to_vec()
                ).unwrap()
            );
            debug!("get_metadata_section: name {}", name);
            if read_metadata_section_name(target) == name {
                let cbuf = llvm::LLVMGetSectionContents(si.llsi);
                let csz = llvm::LLVMGetSectionSize(si.llsi) as usize;
                // The buffer is valid while the object file is around
                let buf: &'a [u8] = slice::from_raw_parts(cbuf as *const u8, csz);
                return Ok(buf);
            }
            llvm::LLVMMoveToNextSection(si.llsi);
        }
    }
    Err(format!("metadata not found: '{}'", filename.display()))
}

pub fn metadata_section_name(target: &Target) -> &'static str {
    // Historical note:
    //
    // When using link.exe it was seen that the section name `.note.rustc`
    // was getting shortened to `.note.ru`, and according to the PE and COFF
    // specification:
    //
    // > Executable images do not use a string table and do not support
    // > section names longer than 8 characters
    //
    // https://msdn.microsoft.com/en-us/library/windows/hardware/gg463119.aspx
    //
    // As a result, we choose a slightly shorter name! As to why
    // `.note.rustc` works on MinGW, that's another good question...

    if target.options.is_like_osx {
        "__DATA,.rustc"
    } else {
        ".rustc"
    }
}

fn read_metadata_section_name(_target: &Target) -> &'static str {
    ".rustc"
}
