// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(non_camel_case_types)]

// The crate store - a central repo for information collected about external
// crates and libraries

pub use self::MetadataBlob::*;

use common;
use creader;
use decoder;
use index;
use loader;

use rustc::dep_graph::DepGraph;
use rustc::hir::def_id::{DefIndex, DefId};
use rustc::hir::map::DefKey;
use rustc::hir::svh::Svh;
use rustc::middle::cstore::ExternCrate;
use rustc::session::config::PanicStrategy;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};

use std::cell::{RefCell, Ref, Cell};
use std::rc::Rc;
use std::path::PathBuf;
use flate::Bytes;
use syntax::ast;
use syntax::attr;
use syntax::codemap;
use syntax_pos;

pub use middle::cstore::{NativeLibraryKind, LinkagePreference};
pub use middle::cstore::{NativeStatic, NativeFramework, NativeUnknown};
pub use middle::cstore::{CrateSource, LinkMeta};

// A map from external crate numbers (as decoded from some crate file) to
// local crate numbers (as generated during this session). Each external
// crate may refer to types in other external crates, and each has their
// own crate numbers.
pub type CrateNumMap = IndexVec<ast::CrateNum, ast::CrateNum>;

pub enum MetadataBlob {
    MetadataVec(Bytes),
    MetadataArchive(loader::ArchiveMetadata),
}

/// Holds information about a syntax_pos::FileMap imported from another crate.
/// See creader::import_codemap() for more information.
pub struct ImportedFileMap {
    /// This FileMap's byte-offset within the codemap of its original crate
    pub original_start_pos: syntax_pos::BytePos,
    /// The end of this FileMap within the codemap of its original crate
    pub original_end_pos: syntax_pos::BytePos,
    /// The imported FileMap's representation within the local codemap
    pub translated_filemap: Rc<syntax_pos::FileMap>
}

pub struct CrateMetadata {
    pub name: String,

    /// Information about the extern crate that caused this crate to
    /// be loaded. If this is `None`, then the crate was injected
    /// (e.g., by the allocator)
    pub extern_crate: Cell<Option<ExternCrate>>,

    pub data: MetadataBlob,
    pub cnum_map: RefCell<CrateNumMap>,
    pub cnum: ast::CrateNum,
    pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
    pub staged_api: bool,

    pub index: index::Index,
    pub xref_index: index::DenseIndex,

    /// For each public item in this crate, we encode a key.  When the
    /// crate is loaded, we read all the keys and put them in this
    /// hashmap, which gives the reverse mapping.  This allows us to
    /// quickly retrace a `DefPath`, which is needed for incremental
    /// compilation support.
    pub key_map: FnvHashMap<DefKey, DefIndex>,

    /// Flag if this crate is required by an rlib version of this crate, or in
    /// other words whether it was explicitly linked to. An example of a crate
    /// where this is false is when an allocator crate is injected into the
    /// dependency list, and therefore isn't actually needed to link an rlib.
    pub explicitly_linked: Cell<bool>,
}

pub struct CachedInlinedItem {
    /// The NodeId of the RootInlinedParent HIR map entry
    pub inlined_root: ast::NodeId,
    /// The local NodeId of the inlined entity
    pub item_id: ast::NodeId,
}

pub struct CStore {
    pub dep_graph: DepGraph,
    metas: RefCell<FnvHashMap<ast::CrateNum, Rc<CrateMetadata>>>,
    /// Map from NodeId's of local extern crate statements to crate numbers
    extern_mod_crate_map: RefCell<NodeMap<ast::CrateNum>>,
    used_crate_sources: RefCell<Vec<CrateSource>>,
    used_libraries: RefCell<Vec<(String, NativeLibraryKind)>>,
    used_link_args: RefCell<Vec<String>>,
    statically_included_foreign_items: RefCell<NodeSet>,
    pub inlined_item_cache: RefCell<DefIdMap<Option<CachedInlinedItem>>>,
    pub defid_for_inlined_node: RefCell<NodeMap<DefId>>,
    pub visible_parent_map: RefCell<DefIdMap<DefId>>,
}

impl CStore {
    pub fn new(dep_graph: &DepGraph) -> CStore {
        CStore {
            dep_graph: dep_graph.clone(),
            metas: RefCell::new(FnvHashMap()),
            extern_mod_crate_map: RefCell::new(FnvHashMap()),
            used_crate_sources: RefCell::new(Vec::new()),
            used_libraries: RefCell::new(Vec::new()),
            used_link_args: RefCell::new(Vec::new()),
            statically_included_foreign_items: RefCell::new(NodeSet()),
            visible_parent_map: RefCell::new(FnvHashMap()),
            inlined_item_cache: RefCell::new(FnvHashMap()),
            defid_for_inlined_node: RefCell::new(FnvHashMap()),
        }
    }

    pub fn next_crate_num(&self) -> ast::CrateNum {
        self.metas.borrow().len() as ast::CrateNum + 1
    }

    pub fn get_crate_data(&self, cnum: ast::CrateNum) -> Rc<CrateMetadata> {
        self.metas.borrow().get(&cnum).unwrap().clone()
    }

    pub fn get_crate_hash(&self, cnum: ast::CrateNum) -> Svh {
        let cdata = self.get_crate_data(cnum);
        decoder::get_crate_hash(cdata.data())
    }

    pub fn set_crate_data(&self, cnum: ast::CrateNum, data: Rc<CrateMetadata>) {
        self.metas.borrow_mut().insert(cnum, data);
    }

    pub fn iter_crate_data<I>(&self, mut i: I) where
        I: FnMut(ast::CrateNum, &Rc<CrateMetadata>),
    {
        for (&k, v) in self.metas.borrow().iter() {
            i(k, v);
        }
    }

    /// Like `iter_crate_data`, but passes source paths (if available) as well.
    pub fn iter_crate_data_origins<I>(&self, mut i: I) where
        I: FnMut(ast::CrateNum, &CrateMetadata, Option<CrateSource>),
    {
        for (&k, v) in self.metas.borrow().iter() {
            let origin = self.opt_used_crate_source(k);
            origin.as_ref().map(|cs| { assert!(k == cs.cnum); });
            i(k, &v, origin);
        }
    }

    pub fn add_used_crate_source(&self, src: CrateSource) {
        let mut used_crate_sources = self.used_crate_sources.borrow_mut();
        if !used_crate_sources.contains(&src) {
            used_crate_sources.push(src);
        }
    }

    pub fn opt_used_crate_source(&self, cnum: ast::CrateNum)
                                 -> Option<CrateSource> {
        self.used_crate_sources.borrow_mut()
            .iter().find(|source| source.cnum == cnum).cloned()
    }

    pub fn reset(&self) {
        self.metas.borrow_mut().clear();
        self.extern_mod_crate_map.borrow_mut().clear();
        self.used_crate_sources.borrow_mut().clear();
        self.used_libraries.borrow_mut().clear();
        self.used_link_args.borrow_mut().clear();
        self.statically_included_foreign_items.borrow_mut().clear();
    }

    pub fn crate_dependencies_in_rpo(&self, krate: ast::CrateNum) -> Vec<ast::CrateNum>
    {
        let mut ordering = Vec::new();
        self.push_dependencies_in_postorder(&mut ordering, krate);
        ordering.reverse();
        ordering
    }

    pub fn push_dependencies_in_postorder(&self,
                                          ordering: &mut Vec<ast::CrateNum>,
                                          krate: ast::CrateNum)
    {
        if ordering.contains(&krate) { return }

        let data = self.get_crate_data(krate);
        for &dep in data.cnum_map.borrow().iter() {
            if dep != krate {
                self.push_dependencies_in_postorder(ordering, dep);
            }
        }

        ordering.push(krate);
    }

    // This method is used when generating the command line to pass through to
    // system linker. The linker expects undefined symbols on the left of the
    // command line to be defined in libraries on the right, not the other way
    // around. For more info, see some comments in the add_used_library function
    // below.
    //
    // In order to get this left-to-right dependency ordering, we perform a
    // topological sort of all crates putting the leaves at the right-most
    // positions.
    pub fn do_get_used_crates(&self, prefer: LinkagePreference)
                              -> Vec<(ast::CrateNum, Option<PathBuf>)> {
        let mut ordering = Vec::new();
        for (&num, _) in self.metas.borrow().iter() {
            self.push_dependencies_in_postorder(&mut ordering, num);
        }
        info!("topological ordering: {:?}", ordering);
        ordering.reverse();
        let mut libs = self.used_crate_sources.borrow()
            .iter()
            .map(|src| (src.cnum, match prefer {
                LinkagePreference::RequireDynamic => src.dylib.clone().map(|p| p.0),
                LinkagePreference::RequireStatic => src.rlib.clone().map(|p| p.0),
            }))
            .collect::<Vec<_>>();
        libs.sort_by(|&(a, _), &(b, _)| {
            let a = ordering.iter().position(|x| *x == a);
            let b = ordering.iter().position(|x| *x == b);
            a.cmp(&b)
        });
        libs
    }

    pub fn add_used_library(&self, lib: String, kind: NativeLibraryKind) {
        assert!(!lib.is_empty());
        self.used_libraries.borrow_mut().push((lib, kind));
    }

    pub fn get_used_libraries<'a>(&'a self)
                              -> &'a RefCell<Vec<(String,
                                                  NativeLibraryKind)>> {
        &self.used_libraries
    }

    pub fn add_used_link_args(&self, args: &str) {
        for s in args.split(' ').filter(|s| !s.is_empty()) {
            self.used_link_args.borrow_mut().push(s.to_string());
        }
    }

    pub fn get_used_link_args<'a>(&'a self) -> &'a RefCell<Vec<String> > {
        &self.used_link_args
    }

    pub fn add_extern_mod_stmt_cnum(&self,
                                    emod_id: ast::NodeId,
                                    cnum: ast::CrateNum) {
        self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
    }

    pub fn add_statically_included_foreign_item(&self, id: ast::NodeId) {
        self.statically_included_foreign_items.borrow_mut().insert(id);
    }

    pub fn do_is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool {
        self.statically_included_foreign_items.borrow().contains(&id)
    }

    pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<ast::CrateNum>
    {
        self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
    }
}

impl CrateMetadata {
    pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
    pub fn name(&self) -> &str { decoder::get_crate_name(self.data()) }
    pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) }
    pub fn disambiguator(&self) -> &str {
        decoder::get_crate_disambiguator(self.data())
    }
    pub fn imported_filemaps<'a>(&'a self, codemap: &codemap::CodeMap)
                                 -> Ref<'a, Vec<ImportedFileMap>> {
        let filemaps = self.codemap_import_info.borrow();
        if filemaps.is_empty() {
            drop(filemaps);
            let filemaps = creader::import_codemap(codemap, &self.data);

            // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
            *self.codemap_import_info.borrow_mut() = filemaps;
            self.codemap_import_info.borrow()
        } else {
            filemaps
        }
    }

    pub fn is_allocator(&self) -> bool {
        let attrs = decoder::get_crate_attributes(self.data());
        attr::contains_name(&attrs, "allocator")
    }

    pub fn needs_allocator(&self) -> bool {
        let attrs = decoder::get_crate_attributes(self.data());
        attr::contains_name(&attrs, "needs_allocator")
    }

    pub fn is_panic_runtime(&self) -> bool {
        let attrs = decoder::get_crate_attributes(self.data());
        attr::contains_name(&attrs, "panic_runtime")
    }

    pub fn needs_panic_runtime(&self) -> bool {
        let attrs = decoder::get_crate_attributes(self.data());
        attr::contains_name(&attrs, "needs_panic_runtime")
    }

    pub fn panic_strategy(&self) -> PanicStrategy {
        decoder::get_panic_strategy(self.data())
    }
}

impl MetadataBlob {
    pub fn as_slice_raw<'a>(&'a self) -> &'a [u8] {
        match *self {
            MetadataVec(ref vec) => &vec[..],
            MetadataArchive(ref ar) => ar.as_slice(),
        }
    }

    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        let slice = self.as_slice_raw();
        let len_offset = 4 + common::metadata_encoding_version.len();
        if slice.len() < len_offset+4 {
            &[] // corrupt metadata
        } else {
            let len = (((slice[len_offset+0] as u32) << 24) |
                       ((slice[len_offset+1] as u32) << 16) |
                       ((slice[len_offset+2] as u32) << 8) |
                       ((slice[len_offset+3] as u32) << 0)) as usize;
            if len <= slice.len() - 4 - len_offset {
                &slice[len_offset + 4..len_offset + len + 4]
            } else {
                &[] // corrupt or old metadata
            }
        }
    }
}
