// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {
    crate::Rule,
    anyhow::{format_err, Error},
    itertools::Itertools,
    pest::iterators::{Pair, Pairs},
    serde::Serialize,
    std::cmp::Ordering,
    std::collections::{BTreeMap, HashSet},
    std::fmt,
    std::str::FromStr,
    thiserror::Error,
};

#[derive(Debug, Error)]
pub enum ParseError {
    #[error("{0} is not yet support")]
    NotYetSupported(String),
    #[error("{0:?} is not expected in this location")]
    UnexpectedToken(Rule),
    #[error("{0} was not included in the input libraries")]
    UnImported(String),
    #[error("{0} is an unknown type")]
    UnrecognizedType(String),
    #[error("Failed to parse because {0:?} is not an integer")]
    NotAnInteger(Rule),
    #[error("Invalid dependencies: {0}")]
    InvalidDeps(String),
    #[error("Expected {0:?} to resolve to a {1:?}.")]
    InvalidConstType(Constant, Ty),
    #[error("Declaration not found in namespace")]
    UnknownDecl,
}

#[derive(PartialEq, Eq, Serialize, Default, Debug, Clone, Hash, PartialOrd, Ord)]
pub struct Attr {
    pub key: String,
    pub val: Option<String>,
}

#[derive(PartialEq, Eq, Serialize, Default, Debug, Clone, Hash, PartialOrd, Ord)]
pub struct Attrs(pub Vec<Attr>);

// namespace is only populated if it's not the current/default one
// TODO(bwb) consider populating it or renaming to be more explicit
#[derive(PartialEq, Debug, Eq, Serialize, Clone, Hash, PartialOrd, Ord)]
pub struct Ident {
    namespace: Option<String>,
    name: String,
}

impl Ident {
    /// Construct an identity. If the second parameter is a fully qualified identity, use that
    /// if it is not qualified, place it under the passed in namespace
    pub fn new(namespace: &str, raw_name: &str) -> Ident {
        let v: Vec<&str> = raw_name.rsplitn(2, '.').collect();
        if v.len() > 1 {
            Ident { namespace: Some(v[1].trim().to_string()), name: v[0].trim().to_string() }
        } else {
            Ident {
                namespace: Some(namespace.trim().to_string()),
                name: raw_name.trim().to_string(),
            }
        }
    }

    pub fn new_raw(raw_name: &str) -> Ident {
        let v: Vec<&str> = raw_name.rsplitn(2, '.').collect();
        if v.len() > 1 {
            Ident { namespace: Some(v[1].trim().to_string()), name: v[0].trim().to_string() }
        } else {
            Ident { namespace: None, name: raw_name.trim().to_string() }
        }
    }

    pub fn fq(&self) -> (Option<String>, String) {
        (self.namespace.clone(), self.name.clone())
    }

    pub fn name(&self) -> &str {
        self.name.as_str()
    }

    // Returns a triplet of data used to sort declarations in a way that's identical to FIDL.
    pub fn order_triplet(&self) -> (String, String, String) {
        (
            // Namespace.
            self.namespace.as_ref().map(|ns| ns.clone()).unwrap_or("".to_string()),
            // Unqualified name.
            self.name.clone(),
            // Fully-qualified name.
            self.namespace
                .as_ref()
                .map(|ns| format!("{}/{}", ns, self.name))
                .unwrap_or(self.name.clone()),
        )
    }

    pub fn is_base_type(&self) -> bool {
        // TODO add more of zx.banjo
        match self.namespace {
            Some(ref n) => n == "zx",
            None => false,
        }
    }
}

impl Attrs {
    #[allow(dead_code)]
    pub fn has_attributes(&self) -> bool {
        self.0.len() > 0
    }

    pub fn has_attribute(&self, key: &str) -> bool {
        self.0.iter().any(|attr| attr.key == key)
    }

    pub fn get_attribute<'a>(&'a self, key: &str) -> Option<&'a String> {
        if let Some(attr) = self.0.iter().find(|attr| attr.key == key) {
            if let Some(ref val) = attr.val {
                Some(val)
            } else {
                None
            }
        } else {
            None
        }
    }

    pub fn from_pair(pair: Pair<'_, Rule>) -> Result<Attrs, ParseError> {
        let mut attrs = Attrs::default();
        let mut doc_string: Option<String> = None; // String::default();
        for inner_pair in pair.into_inner() {
            match inner_pair.as_rule() {
                Rule::doc_comment => {
                    if doc_string.is_none() {
                        doc_string = Some(String::default())
                    }
                    if let Some(ref mut doc_string) = doc_string {
                        *doc_string += inner_pair.as_str().split_at(3).1;
                    }
                }
                Rule::attribute_list => {
                    for attrib in inner_pair.into_inner() {
                        let ap = attrib.as_str();
                        if !ap.contains("=") {
                            attrs.0.push(Attr { key: String::from(ap.trim()), val: None });
                        } else {
                            let split: Vec<&str> = ap.split("=").collect();
                            // Strip whitespace and quotes.
                            let val = split[1].trim();
                            let val = val.chars().skip(1).take(val.len() - 2).collect();
                            attrs
                                .0
                                .push(Attr { key: String::from(split[0].trim()), val: Some(val) });
                        }
                    }
                }
                _ => unreachable!(),
            }
        }
        if doc_string.is_some() {
            attrs.0.push(Attr { key: String::from("Doc"), val: doc_string });
        }
        Ok(attrs)
    }
}

#[derive(PartialEq, Eq, Clone, Serialize, Debug, Hash, PartialOrd, Ord)]
pub struct Constant(pub String);

impl Constant {
    pub fn from_str(string: &str) -> Self {
        Constant(string.to_string())
    }
}

impl std::fmt::Display for Constant {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

#[derive(PartialEq, Eq, Clone, Serialize, Debug, Hash, PartialOrd, Ord)]
pub enum HandleTy {
    None,
    Process,
    Thread,
    Vmo,
    Channel,
    Event,
    Port,
    Interrupt,
    PciDevice,
    Log,
    Socket,
    Resource,
    EventPair,
    Job,
    Vmar,
    Fifo,
    Guest,
    VCpu,
    Timer,
    IoMmu,
    Bti,
    Profile,
    Pmt,
    SuspendToken,
    Pager,
    Exception,
    Clock,
    Stream,
    MsiAllocation,
    MsiInterrupt,
}

#[derive(PartialEq, Eq, Clone, Serialize, Debug, Hash, PartialOrd, Ord)]
pub enum Ty {
    Bool,
    Int8,
    Int16,
    Int32,
    Int64,
    UInt8,
    UInt16,
    UInt32,
    UInt64,
    Float32,
    Float64,
    Str { size: Option<Constant>, nullable: bool },
    Vector { ty: Box<Ty>, size: Option<Constant>, nullable: bool },
    Array { ty: Box<Ty>, size: Constant },
    Protocol,
    Struct,
    Union,
    Enum,
    Handle { ty: HandleTy, reference: bool },
    // TODO rename this to something less confusing
    Identifier { id: Ident, reference: bool },
}

impl fmt::Display for Ty {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Ty::UInt32 => write!(f, "UInt32"),
            Ty::Identifier { .. } => write!(f, "<Ident>"),
            _ => Err(fmt::Error),
        }
    }
}

impl Ty {
    pub fn is_primitive(&self, ast: &BanjoAst) -> bool {
        match self {
            Ty::Identifier { id, .. } => {
                if id.is_base_type() {
                    return true;
                } else {
                    let resolved_type = ast.id_to_type(id);
                    return resolved_type.is_primitive(&ast);
                }
            }
            Ty::Struct { .. } => false,
            Ty::Union { .. } => false,
            Ty::Protocol { .. } => false,
            Ty::Enum { .. } => true,
            Ty::Str { .. } | Ty::Vector { .. } | Ty::Array { .. } | Ty::Handle { .. } => false,
            _ => true,
        }
    }

    pub fn is_reference(&self) -> bool {
        match self {
            Ty::Str { nullable, .. } => *nullable,
            Ty::Vector { nullable, .. } => *nullable,
            Ty::Identifier { reference, .. } => *reference,
            Ty::Handle { reference, .. } => *reference,
            _ => false,
        }
    }

    pub fn from_pair(ns: &str, pair: &Pair<'_, Rule>) -> Result<Self, ParseError> {
        let rule = pair.as_rule();
        match rule {
            Rule::primitive_type => match pair.as_str() {
                "bool" => Ok(Ty::Bool),
                "int8" => Ok(Ty::Int8),
                "int16" => Ok(Ty::Int16),
                "int32" => Ok(Ty::Int32),
                "int64" => Ok(Ty::Int64),
                "uint8" => Ok(Ty::UInt8),
                "uint16" => Ok(Ty::UInt16),
                "uint32" => Ok(Ty::UInt32),
                "uint64" => Ok(Ty::UInt64),
                "float32" => Ok(Ty::Float32),
                "float64" => Ok(Ty::Float64),
                _e => Err(ParseError::UnrecognizedType(pair.as_str().to_string())),
            },
            Rule::handle_type => {
                let mut ty = HandleTy::None;
                let mut reference = false;
                for inner_pair in pair.clone().into_inner() {
                    match inner_pair.as_rule() {
                        Rule::handle_subtype => {
                            ty = match inner_pair.as_str() {
                                "NONE" => HandleTy::None,
                                "PROCESS" => HandleTy::Process,
                                "THREAD" => HandleTy::Thread,
                                "VMO" => HandleTy::Vmo,
                                "CHANNEL" => HandleTy::Channel,
                                "EVENT" => HandleTy::Event,
                                "PORT" => HandleTy::Port,
                                "INTERRUPT" => HandleTy::Interrupt,
                                "PCI_DEVICE" => HandleTy::PciDevice,
                                "LOG" => HandleTy::Log,
                                "SOCKET" => HandleTy::Socket,
                                "RESOURCE" => HandleTy::Resource,
                                "EVENTPAIR" => HandleTy::EventPair,
                                "JOB" => HandleTy::Job,
                                "VMAR" => HandleTy::Vmar,
                                "FIFO" => HandleTy::Fifo,
                                "GUEST" => HandleTy::Guest,
                                "VCPU" => HandleTy::VCpu,
                                "TIMER" => HandleTy::Timer,
                                "IOMMU" => HandleTy::IoMmu,
                                "BTI" => HandleTy::Bti,
                                "PROFILE" => HandleTy::Profile,
                                "PMT" => HandleTy::Pmt,
                                "SUSPEND_TOKEN" => HandleTy::SuspendToken,
                                "PAGER" => HandleTy::Pager,
                                "EXCEPTION" => HandleTy::Exception,
                                "CLOCK" => HandleTy::Clock,
                                "STREAM" => HandleTy::Stream,
                                "MSI_ALLOCATION" => HandleTy::MsiAllocation,
                                "MSI_INTERRUPT" => HandleTy::MsiInterrupt,
                                _e => {
                                    return Err(ParseError::UnrecognizedType(
                                        inner_pair.as_str().to_string(),
                                    ));
                                }
                            }
                        }
                        Rule::reference => {
                            reference = true;
                        }
                        _e => {
                            return Err(ParseError::UnrecognizedType(
                                inner_pair.as_str().to_string(),
                            ));
                        }
                    }
                }
                Ok(Ty::Handle { ty, reference })
            }
            Rule::integer_type => match pair.as_str() {
                "int8" => Ok(Ty::Int8),
                "int16" => Ok(Ty::Int16),
                "int32" => Ok(Ty::Int32),
                "int64" => Ok(Ty::Int64),
                "uint8" => Ok(Ty::UInt8),
                "uint16" => Ok(Ty::UInt16),
                "uint32" => Ok(Ty::UInt32),
                "uint64" => Ok(Ty::UInt64),
                _e => Err(ParseError::NotAnInteger(rule)),
            },
            Rule::array_type => {
                let vec_contents: Vec<Pair<'_, Rule>> = pair.clone().into_inner().collect();
                let ty = Box::new(Ty::from_pair(ns, &vec_contents[0])?);
                let size = Constant::from_str(vec_contents[1].as_str());
                Ok(Ty::Array { ty, size })
            }
            Rule::identifier_type => {
                let mut iter = pair.clone().into_inner();
                let id = iter.next().unwrap().as_str();
                let reference = if let Some(pair) = iter.next() {
                    match pair.as_rule() {
                        Rule::reference => true,
                        e => {
                            return Err(ParseError::UnexpectedToken(e));
                        }
                    }
                } else {
                    false
                };
                Ok(Ty::Identifier { id: Ident::new(ns, id), reference })
            }
            Rule::string_type => {
                let mut size = None;
                let mut nullable = false;
                for inner_pair in pair.clone().into_inner() {
                    match inner_pair.as_rule() {
                        Rule::constant => {
                            if inner_pair.as_str() != "MAX" {
                                size = Some(Constant::from_str(inner_pair.as_str()));
                            }
                        }
                        Rule::reference => {
                            nullable = true;
                        }
                        e => {
                            return Err(ParseError::UnexpectedToken(e));
                        }
                    }
                }
                Ok(Ty::Str { size, nullable })
            }
            Rule::vector_type => {
                let mut iter = pair.clone().into_inner();
                let ty = Box::new(Ty::from_pair(ns, &iter.next().unwrap())?);
                let mut size = None;
                let mut nullable = false;
                for inner_pair in iter {
                    match inner_pair.as_rule() {
                        Rule::constant => {
                            if inner_pair.as_str() != "MAX" {
                                size = Some(Constant::from_str(inner_pair.as_str()));
                            }
                        }
                        Rule::reference => {
                            nullable = true;
                        }
                        e => {
                            return Err(ParseError::UnexpectedToken(e));
                        }
                    }
                }
                Ok(Ty::Vector { ty, size, nullable })
            }
            _e => Err(ParseError::UnrecognizedType(pair.as_str().to_string())),
        }
    }
}

#[derive(PartialEq, Eq, Serialize, Debug, Hash, PartialOrd, Ord)]
pub struct StructField {
    pub attributes: Attrs,
    pub ty: Ty,
    pub ident: Ident,
    pub val: Option<Constant>,
}

impl StructField {
    pub fn from_pair(ns: &str, pair: Pair<'_, Rule>) -> Result<Self, ParseError> {
        let mut attributes = Attrs::default();
        let mut ty = None;
        let mut ident = String::default();
        let mut val = None;
        for inner_pair in pair.into_inner() {
            match inner_pair.as_rule() {
                Rule::attributes => attributes = Attrs::from_pair(inner_pair)?,
                Rule::ident => ident = String::from(inner_pair.as_str()),
                Rule::constant => val = Some(Constant::from_str(inner_pair.as_str())),
                _ => ty = Some(Ty::from_pair(ns, &inner_pair)?),
            };
        }
        Ok(StructField {
            attributes: attributes,
            ty: ty.unwrap(),
            ident: Ident::new_raw(ident.as_str()),
            val: val,
        })
    }
}

#[derive(PartialEq, Eq, Serialize, Debug, Hash, PartialOrd, Ord, Clone)]
pub struct UnionField {
    pub attributes: Attrs,
    pub ty: Ty,
    pub ident: Ident,
}
impl UnionField {
    pub fn from_pair(ns: &str, pair: Pair<'_, Rule>) -> Result<Self, ParseError> {
        let fields: Vec<Pair<'_, Rule>> = pair.into_inner().collect();
        let ty = &fields[1];
        Ok(UnionField {
            attributes: Attrs::from_pair(fields[0].clone())?,
            ty: Ty::from_pair(ns, ty)?,
            ident: Ident::new_raw(fields[2].as_str()),
        })
    }
}

#[derive(PartialEq, Eq, Serialize, Debug, Hash, PartialOrd, Ord, Clone)]
pub struct EnumVariant {
    pub attributes: Attrs,
    pub name: String,
    pub value: Constant,
}

impl EnumVariant {
    pub fn from_pair(pair: Pair<'_, Rule>) -> Result<Self, ParseError> {
        let fields: Vec<Pair<'_, Rule>> = pair.into_inner().collect();
        Ok(EnumVariant {
            attributes: Attrs::from_pair(fields[0].clone())?,
            name: String::from(fields[1].as_str()),
            value: Constant::from_str(fields[2].as_str()),
        })
    }
}

#[derive(PartialEq, Eq, Serialize, Debug, Hash, PartialOrd, Ord)]
pub struct Method {
    pub attributes: Attrs,
    pub name: String,
    pub in_params: Vec<(String, Ty, Attrs)>,
    pub out_params: Vec<(String, Ty, Attrs)>,
}

impl Method {
    #[allow(dead_code)]
    pub fn name_to_ty(&self, arg_name: &str) -> Result<&Ty, Error> {
        for (name, ty, _) in self.in_params.iter() {
            if arg_name == name {
                return Ok(ty);
            }
        }
        Err(format_err!("`{:?}` arg not found in method `{:?}`", arg_name, self.name))
    }

    pub fn from_pair(ns: &str, pair: Pair<'_, Rule>) -> Result<Self, ParseError> {
        let mut attributes = Attrs::default();
        let mut name = String::default();
        let mut in_params = Vec::new();
        let mut out_params = Vec::new();
        for inner_pair in pair.into_inner() {
            match inner_pair.as_rule() {
                Rule::attributes => {
                    attributes = Attrs::from_pair(inner_pair)?;
                }
                Rule::protocol_parameters => {
                    let mut fields: Vec<Pair<'_, Rule>> = inner_pair.into_inner().collect();
                    name = String::from(fields[0].as_str());
                    // TODO cleaner way of getting in/out params
                    let inner_params = fields.remove(1);
                    for in_pair in inner_params.into_inner() {
                        match in_pair.as_rule() {
                            Rule::parameter => {
                                let mut param_fields: Vec<Pair<'_, Rule>> =
                                    in_pair.into_inner().collect();
                                let mut attributes = Attrs::default();
                                if param_fields.len() > 2 {
                                    attributes = Attrs::from_pair(param_fields.remove(0))?;
                                }
                                let ty = Ty::from_pair(ns, &param_fields.get(0).unwrap())?;
                                let name = String::from(param_fields.get(1).unwrap().as_str());
                                in_params.push((name, ty, attributes));
                            }
                            e => return Err(ParseError::UnexpectedToken(e)),
                        }
                    }
                    // might not have any return paramaters
                    if fields.len() > 1 {
                        let inner_params = fields.remove(1);
                        for in_pair in inner_params.into_inner() {
                            match in_pair.as_rule() {
                                Rule::parameter => {
                                    let mut param_fields: Vec<Pair<'_, Rule>> =
                                        in_pair.into_inner().collect();
                                    let mut attributes = Attrs::default();
                                    if param_fields.len() > 2 {
                                        attributes = Attrs::from_pair(param_fields.remove(0))?;
                                    }
                                    let ty = Ty::from_pair(ns, &param_fields.get(0).unwrap())?;
                                    let name = String::from(param_fields.get(1).unwrap().as_str());
                                    out_params.push((name, ty, attributes));
                                }
                                e => return Err(ParseError::UnexpectedToken(e)),
                            }
                        }
                    }
                }
                e => return Err(ParseError::UnexpectedToken(e)),
            }
        }
        Ok(Method { attributes, name, in_params, out_params })
    }
}

#[derive(PartialEq, Eq, Serialize, Debug, Hash)]
pub enum Decl {
    Struct { attributes: Attrs, name: Ident, fields: Vec<StructField> },
    Union { attributes: Attrs, name: Ident, fields: Vec<UnionField> },
    Enum { attributes: Attrs, name: Ident, ty: Ty, variants: Vec<EnumVariant> },
    Constant { attributes: Attrs, name: Ident, ty: Ty, value: Constant },
    Protocol { attributes: Attrs, name: Ident, methods: Vec<Method>, placeholders: Vec<Ty> },
    Resource { attributes: Attrs, ty: Ty, values: Vec<Constant> },
    Alias(Ident, Ident),
}

impl Decl {
    // Returns an object used to order declaration instances.
    //
    // Currently a tuple of namespace + short name + fully-qualified name.
    fn get_order(&self) -> Option<(String, String, String)> {
        // Declarations are alphabetically ordered here. Note however that the list of 0-dependency
        // declarations is processed from the back in `validate_declaration_deps`, resulting in
        // descending alhpabetical order.
        match self {
            Decl::Protocol { name, .. } => Some(name.order_triplet()),
            Decl::Struct { name, .. } => Some(name.order_triplet()),
            Decl::Union { name, .. } => Some(name.order_triplet()),
            Decl::Enum { name, .. } => Some(name.order_triplet()),
            Decl::Alias(to, _from) => Some(to.order_triplet()),
            Decl::Constant { name, .. } => Some(name.order_triplet()),
            Decl::Resource { .. } => None,
        }
    }
}

impl Ord for Decl {
    fn cmp(&self, other: &Self) -> Ordering {
        let self_order = self.get_order();
        let other_order = other.get_order();
        if self_order == None || other_order == None {
            return self_order.cmp(&other_order);
        }
        let (self_ns, self_name, self_flat_name) = self_order.unwrap();
        let (other_ns, other_name, other_flat_name) = other_order.unwrap();
        if self_ns != other_ns {
            return self_flat_name.cmp(&other_flat_name);
        } else {
            return self_name.cmp(&other_name);
        }
    }
}

impl PartialOrd for Decl {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

#[derive(PartialEq, Serialize, Debug)]
pub struct BanjoAst {
    pub primary_namespace: String,
    pub namespaces: BTreeMap<String, Vec<Decl>>,
}

// Placeholder declarations are necessary to achieve an ordering identical to FIDL's.
// The name of these generated declarations is the same as in FIDL.

#[derive(Debug)]
pub struct PlaceholderGenerator {
    counter: u32,
}

const ANONYMOUS_PREFIX: &str = "SomeLongAnonymousPrefix";

impl PlaceholderGenerator {
    fn new() -> Self {
        Self { counter: 0 }
    }

    fn get(&mut self, ns: &str, params: &Vec<(String, Ty, Attrs)>) -> (Decl, Ty) {
        let ident = Ident::new(ns, format!("{}{}", ANONYMOUS_PREFIX, self.counter).as_str());
        let fields: Vec<StructField> = params
            .iter()
            .map(|t| {
                let (name, ty, _) = t;
                return StructField {
                    attributes: Attrs(Vec::new()),
                    ty: ty.clone(),
                    ident: Ident::new(ns, name),
                    val: None,
                };
            })
            .collect();
        let result =
            Decl::Struct { attributes: Attrs(Vec::new()), name: ident.clone(), fields: fields };
        self.counter += 1;
        (result, Ty::Identifier { id: ident, reference: false })
    }
}

pub fn is_placeholder_struct(decl: &Decl) -> bool {
    match decl {
        Decl::Struct { name, .. } => name.name.starts_with(ANONYMOUS_PREFIX),
        _ => false,
    }
}

impl BanjoAst {
    pub fn id_to_decl(&self, fq_ident: &Ident) -> Result<&Decl, ParseError> {
        self.maybe_id_to_decl(fq_ident).ok_or(ParseError::UnknownDecl)
    }

    pub fn maybe_id_to_decl(&self, fq_ident: &Ident) -> Option<&Decl> {
        let (namespace, ident) = fq_ident.fq();
        for decl in self.namespaces[&namespace.unwrap_or(self.primary_namespace.clone())].iter() {
            match decl {
                Decl::Protocol { name, .. } => {
                    if name.name() == ident {
                        return Some(decl);
                    }
                }
                Decl::Struct { name, .. } => {
                    if name.name() == ident {
                        return Some(decl);
                    }
                }
                Decl::Union { name, .. } => {
                    if name.name() == ident {
                        return Some(decl);
                    }
                }
                Decl::Enum { name, .. } => {
                    if name.name() == ident {
                        return Some(decl);
                    }
                }
                Decl::Alias(to, _from) => {
                    if to == fq_ident {
                        return Some(decl);
                    }
                }
                Decl::Constant { name, .. } => {
                    if name.name() == ident {
                        return Some(decl);
                    }
                }
                Decl::Resource { .. } => {}
            }
        }
        None
    }

    pub fn id_to_type(&self, fq_ident: &Ident) -> Ty {
        match self.maybe_id_to_type(fq_ident) {
            Some(ty) => ty,
            None => panic!("Unidentified {:?}", fq_ident),
        }
    }

    pub fn maybe_id_to_type(&self, fq_ident: &Ident) -> Option<Ty> {
        let (ns, ident) = fq_ident.fq();
        match ident.as_str() {
            "bool" => return Some(Ty::Bool),
            "int8" => return Some(Ty::Int8),
            "int16" => return Some(Ty::Int16),
            "int32" => return Some(Ty::Int32),
            "int64" => return Some(Ty::Int64),
            "uint8" => return Some(Ty::UInt8),
            "uint16" => return Some(Ty::UInt16),
            "uint32" => return Some(Ty::UInt32),
            "uint64" => return Some(Ty::UInt64),
            "float32" => return Some(Ty::Float32),
            "float64" => return Some(Ty::Float64),
            _ => {}
        };

        let namespace = match ns {
            Some(ref n) => n,
            None => &self.primary_namespace,
        };

        for decl in self.namespaces[namespace].iter() {
            match decl {
                Decl::Protocol { name, .. } => {
                    if name.name() == ident {
                        return Some(Ty::Protocol);
                    }
                }
                Decl::Struct { name, .. } => {
                    if name.name() == ident {
                        return Some(Ty::Struct);
                    }
                }
                Decl::Union { name, .. } => {
                    if name.name() == ident {
                        return Some(Ty::Union);
                    }
                }
                Decl::Enum { name, variants, .. } => {
                    if name.name() == ident {
                        return Some(Ty::Enum);
                    }
                    for variant in variants.iter() {
                        if variant.name == ident {
                            return Some(Ty::Identifier { id: name.clone(), reference: false });
                        }
                    }
                }
                Decl::Alias(to, from) => {
                    if to.name == ident {
                        return self.maybe_id_to_type(from);
                    }
                }
                Decl::Constant { name, ty, .. } => {
                    if name.name() == ident {
                        return Some((*ty).clone());
                    }
                }
                Decl::Resource { .. } => {}
            }
        }
        None
    }

    pub fn id_to_attributes(&self, fq_ident: &Ident) -> Option<&Attrs> {
        let (ns, ident) = fq_ident.fq();

        let namespace = match ns {
            Some(ref n) => n,
            None => &self.primary_namespace,
        };

        for decl in self.namespaces[namespace].iter() {
            match decl {
                Decl::Protocol { name, attributes, .. } => {
                    if name.name() == ident {
                        return Some(attributes);
                    }
                }
                Decl::Struct { name, attributes, .. } => {
                    if name.name() == ident {
                        return Some(attributes);
                    }
                }
                Decl::Union { name, attributes, .. } => {
                    if name.name() == ident {
                        return Some(attributes);
                    }
                }
                Decl::Enum { name, attributes, .. } => {
                    if name.name() == ident {
                        return Some(attributes);
                    }
                }
                Decl::Alias(to, from) => {
                    if to.name == ident {
                        return self.id_to_attributes(from);
                    }
                }
                Decl::Constant { name, attributes, .. } => {
                    if name.name() == ident {
                        return Some(attributes);
                    }
                }
                Decl::Resource { .. } => {}
            }
        }
        None
    }

    /// Parses a declaration represented by a `Rule` object generated by the parser.
    ///
    /// The declaration is attached to the given namespace `ns`.
    /// `placeholder_generator` is used to provide anonymous types which participate in recreating
    /// a declaration ordering identical to FIDL's.
    pub fn parse_decl(
        pair: Pair<'_, Rule>,
        ns: &str,
        _namespaces: &BTreeMap<String, Vec<Decl>>,
        placeholder_generator: &mut PlaceholderGenerator,
    ) -> Result<Vec<Decl>, ParseError> {
        match pair.as_rule() {
            Rule::struct_declaration => {
                let mut attributes = Attrs::default();
                let mut name = String::default();
                let mut fields = Vec::default();
                for inner_pair in pair.into_inner() {
                    match inner_pair.as_rule() {
                        Rule::attributes => {
                            attributes = Attrs::from_pair(inner_pair)?;
                        }
                        Rule::ident => {
                            name = String::from(inner_pair.as_str().trim());
                        }
                        Rule::struct_field => fields.push(StructField::from_pair(ns, inner_pair)?),
                        e => return Err(ParseError::UnexpectedToken(e)),
                    }
                }
                Ok(vec![Decl::Struct { attributes, name: Ident::new(ns, &name), fields }])
            }
            Rule::enum_declaration => {
                let mut attributes = Attrs::default();
                let mut name = String::default();
                let mut variants = Vec::default();
                let mut ty = Ty::UInt32;
                for inner_pair in pair.into_inner() {
                    match inner_pair.as_rule() {
                        Rule::attributes => {
                            attributes = Attrs::from_pair(inner_pair)?;
                        }
                        Rule::ident => {
                            name = String::from(inner_pair.as_str().trim());
                        }
                        Rule::integer_type | Rule::identifier_type => {
                            ty = Ty::from_pair(ns, &inner_pair)?;
                        }
                        Rule::enum_field => variants.push(EnumVariant::from_pair(inner_pair)?),
                        e => return Err(ParseError::UnexpectedToken(e)),
                    }
                }
                Ok(vec![Decl::Enum {
                    attributes,
                    name: Ident::new(ns, name.as_str()),
                    ty,
                    variants,
                }])
            }
            Rule::union_declaration => {
                let mut attributes = Attrs::default();
                let mut name = String::default();
                let mut fields = Vec::default();
                for inner_pair in pair.into_inner() {
                    match inner_pair.as_rule() {
                        Rule::attributes => {
                            attributes = Attrs::from_pair(inner_pair)?;
                        }
                        Rule::ident => {
                            name = String::from(inner_pair.as_str().trim());
                        }
                        Rule::union_field => fields.push(UnionField::from_pair(ns, inner_pair)?),
                        e => return Err(ParseError::UnexpectedToken(e)),
                    }
                }
                Ok(vec![Decl::Union { attributes, name: Ident::new(ns, name.as_str()), fields }])
            }
            // TODO extend to be more expressive for banjo
            Rule::protocol_declaration => {
                let mut attributes = Attrs::default();
                let mut name = String::default();
                let mut methods = Vec::default();
                for inner_pair in pair.into_inner() {
                    match inner_pair.as_rule() {
                        Rule::attributes => {
                            attributes = Attrs::from_pair(inner_pair)?;
                        }
                        Rule::ident => {
                            name = String::from(inner_pair.as_str());
                        }
                        Rule::protocol_method => methods.push(Method::from_pair(ns, inner_pair)?),
                        e => return Err(ParseError::UnexpectedToken(e)),
                    }
                }
                let mut decls: Vec<Decl> = Vec::new();
                let mut placeholders: Vec<Ty> = Vec::new();
                // Generate an anonymous type for each method.
                // This ensures the protocol is properly ordered in the list of declarations.
                for method in &methods {
                    let (in_decl, in_ty) = placeholder_generator.get(ns, &method.in_params);
                    placeholders.push(in_ty);
                    decls.push(in_decl);
                    let (out_decl, out_ty) = placeholder_generator.get(ns, &method.out_params);
                    placeholders.push(out_ty);
                    decls.push(out_decl);
                }
                decls.push(Decl::Protocol {
                    attributes,
                    name: Ident::new(ns, name.as_str()),
                    methods,
                    placeholders,
                });
                Ok(decls)
            }
            Rule::const_declaration => {
                let mut attributes = Attrs::default();
                let mut name = String::default();
                let mut ty = Ty::UInt32;
                let mut value = Constant(String::from(""));
                for inner_pair in pair.into_inner() {
                    match inner_pair.as_rule() {
                        Rule::attributes => {
                            attributes = Attrs::from_pair(inner_pair)?;
                        }
                        Rule::ident => {
                            name = String::from(inner_pair.as_str());
                        }
                        Rule::identifier_type | Rule::string_type | Rule::primitive_type => {
                            ty = Ty::from_pair(ns, &inner_pair)?;
                        }
                        Rule::constant => {
                            value = Constant::from_str(inner_pair.clone().as_span().as_str());
                        }
                        e => return Err(ParseError::UnexpectedToken(e)),
                    }
                }
                Ok(vec![Decl::Constant {
                    attributes,
                    name: Ident::new(ns, name.as_str()),
                    ty,
                    value,
                }])
            }
            Rule::resource_declaration => {
                let mut attributes = Attrs::default();
                let mut ty = Ty::UInt32;
                let mut values = Vec::default();
                for inner_pair in pair.into_inner() {
                    match inner_pair.as_rule() {
                        Rule::attributes => {
                            attributes = Attrs::from_pair(inner_pair)?;
                        }
                        Rule::handle_type | Rule::identifier_type => {
                            ty = Ty::from_pair(ns, &inner_pair)?;
                        }
                        Rule::constant => {
                            values.push(Constant::from_str(inner_pair.clone().as_span().as_str()));
                        }
                        e => return Err(ParseError::UnexpectedToken(e)),
                    }
                }
                Ok(vec![Decl::Resource { attributes, ty, values }])
            }
            Rule::using_decl => {
                let contents: Vec<&str> = pair.clone().into_inner().map(|p| p.as_str()).collect();
                Ok(vec![Decl::Alias(Ident::new(ns, contents[0]), Ident::new(ns, contents[1]))])
            }
            Rule::alias_declaration => {
                let mut to = String::default();
                let mut from = String::default();
                for inner_pair in pair.into_inner() {
                    match inner_pair.as_rule() {
                        Rule::ident => {
                            if to.is_empty() {
                                to = String::from(inner_pair.as_str());
                            } else {
                                from = String::from(inner_pair.as_str());
                            }
                        }
                        Rule::attributes => {}
                        e => return Err(ParseError::UnexpectedToken(e)),
                    }
                }
                Ok(vec![Decl::Alias(Ident::new(ns, to.as_str()), Ident::new(ns, from.as_str()))])
            }
            e => Err(ParseError::UnexpectedToken(e)),
        }
    }

    /// Finds the `Decl` in the AST for a `Ty` found inside of another `Decl`.
    /// If |ignore_ref| is true and |ty| is a reference to an identifier, `None`
    /// will be returned instead of the appropriate `Decl`.
    pub fn type_to_decl(&self, ty: &Ty, ignore_ref: bool) -> Option<&Decl> {
        match ty {
            Ty::Array { ref ty, .. } => self.type_to_decl(ty, ignore_ref),
            Ty::Vector { ref ty, .. } => self.type_to_decl(ty, ignore_ref),
            Ty::Identifier { id, reference } => {
                // don't add edge for a reference
                if ignore_ref && *reference {
                    return None;
                }

                let (maybe_ns, ident) = id.fq();
                let ns = maybe_ns.as_ref().unwrap_or(&self.primary_namespace);
                for decl in self.namespaces[ns].iter() {
                    match decl {
                        Decl::Union { name, .. }
                        | Decl::Constant { name, .. }
                        | Decl::Protocol { name, .. }
                        | Decl::Enum { name, .. }
                        | Decl::Struct { name, .. } => {
                            if name.name() == ident {
                                return Some(decl);
                            }
                        }
                        Decl::Alias(to, _from) => {
                            if to == id {
                                return Some(decl);
                            }
                        }
                        Decl::Resource { .. } => {}
                    }
                }

                if id.is_base_type() {
                    for decl in self.namespaces["zx"].iter() {
                        match decl {
                            Decl::Alias(to, _) => {
                                if to == id {
                                    return Some(decl);
                                }
                            }
                            _ => {}
                        }
                    }
                }

                None
            }
            Ty::Handle { .. } => Some(
                self.id_to_decl(&Ident::new("zx", "handle")).expect("Could not find zx.handle"),
            ),
            _ => None,
        }
    }

    #[allow(dead_code)]
    pub fn is_resource(&self, ty: &Ty) -> bool {
        match ty {
            Ty::Identifier { id, .. } => {
                let target_id = id;
                for decl in self.namespaces[&self.primary_namespace].iter() {
                    match decl {
                        Decl::Resource { ty, .. } => match ty {
                            Ty::Identifier { id, .. } => {
                                if id == target_id {
                                    return true;
                                }
                            }
                            _ => {}
                        },
                        _ => {}
                    }
                }
                false
            }
            Ty::Handle { ty, .. } => {
                let handle_type = ty;
                for decl in self.namespaces[&self.primary_namespace].iter() {
                    match decl {
                        Decl::Resource { ty, .. } => match ty {
                            Ty::Handle { ty, .. } => {
                                if ty == handle_type {
                                    return true;
                                }
                            }
                            _ => {}
                        },
                        _ => {}
                    }
                }
                false
            }
            _ => false,
        }
    }

    // An edge from D1 to D2 means that a C needs to see the declaration
    // of D1 before the declaration of D2. For instance, given the banjo
    //     struct D2 { D1 d; };
    //     struct D1 { int32 x; };
    // D1 has an edge pointing to D2. Note that struct and union pointers,
    // unlike inline structs or unions, do not have dependency edges.
    fn decl_dependencies(&self, decl: &Decl) -> Result<HashSet<&Decl>, ParseError> {
        let mut edges = HashSet::new();

        let mut maybe_add_decl = |ty, ignore_ref| {
            if let Some(type_decl) = self.type_to_decl(ty, ignore_ref) {
                match type_decl {
                    // FIDL omits dependencies on protocols.
                    Decl::Protocol { .. } => (),
                    _ => {
                        edges.insert(type_decl);
                    }
                }
            }
        };

        match decl {
            Decl::Protocol { placeholders, .. } => {
                for placeholder in placeholders {
                    maybe_add_decl(&placeholder, false);
                }
            }
            Decl::Struct { fields, .. } => {
                for field in fields {
                    maybe_add_decl(&field.ty, true);
                }
            }
            Decl::Union { fields, .. } => {
                for field in fields {
                    maybe_add_decl(&field.ty, true);
                }
            }
            Decl::Alias(_to, from) => {
                maybe_add_decl(&self.id_to_type(from), false);
            }
            Decl::Constant { ty, .. } => {
                maybe_add_decl(&ty, false);
            }
            // Enum cannot have dependencies.
            Decl::Enum { .. } => (),
            Decl::Resource { .. } => (),
        };

        Ok(edges)
    }

    /// Validates that the declarations are cycle free and returns declaration ordering.
    pub fn validate_declaration_deps(&self) -> Result<Vec<&Decl>, ParseError> {
        // The number of undelcared dependencies for each decl.
        let mut degrees: BTreeMap<&Decl, u32> = BTreeMap::new();
        // Records the decls that depend on each other.
        let mut inverse_dependencies: BTreeMap<&Decl, Vec<&Decl>> = BTreeMap::new();

        for decl in self.namespaces.iter().flat_map(|(_, decls)| decls.iter()) {
            degrees.insert(&decl, 0);
        }

        for decl in self.namespaces.iter().flat_map(|(_, decls)| decls.iter()) {
            let deps = self.decl_dependencies(&decl)?;
            for dep in deps.iter().filter(|&dep| dep != &decl) {
                let entry = degrees.get_mut(&decl).unwrap();
                *entry += 1;
                let entry = inverse_dependencies.entry(&dep).or_insert(Vec::new());
                entry.push(&decl);
            }
        }

        // Remove mutability.
        let inverse_dependencies = inverse_dependencies;

        // Start with all decls that have no incoming edges.
        // The list is initially sorted in ascending order and newly-available declarations are
        // simply added to the back of the list.
        let mut decls_without_deps = degrees
            .iter()
            .filter(|(_, &degrees)| degrees == 0)
            .map(|(&decl, _)| decl)
            .sorted()
            .collect::<Vec<_>>();

        let mut decl_order = Vec::new();
        // Pull one out of the queue.
        while let Some(decl) = decls_without_deps.pop() {
            assert_eq!(degrees.get(decl), Some(&0));
            decl_order.push(decl);

            // Decrement the incoming degree of all other decls it points to.
            if let Some(inverse_deps) = inverse_dependencies.get(decl) {
                for inverse_dep in inverse_deps.iter().sorted() {
                    let degree = degrees.get_mut(inverse_dep).unwrap();
                    assert_ne!(*degree, 0);
                    *degree -= 1;
                    if *degree == 0 {
                        decls_without_deps.push(inverse_dep);
                    }
                }
            }
        }

        if decl_order.len() != degrees.len() {
            // We didn't visit all the edges! There was a cycle.
            return Err(ParseError::InvalidDeps(String::from(
                "There is a cycle in the declarations",
            )));
        }

        Ok(decl_order
            .into_iter()
            .filter(|decl| {
                if is_placeholder_struct(decl) {
                    return false;
                }
                let ident: Option<&Ident> = match decl {
                    Decl::Protocol { name, .. } => Some(name),
                    Decl::Struct { name, .. } => Some(name),
                    Decl::Union { name, .. } => Some(name),
                    Decl::Enum { name, .. } => Some(name),
                    Decl::Alias(to, _from) => Some(to),
                    Decl::Constant { name, .. } => Some(name),
                    Decl::Resource { .. } => None,
                };
                match ident {
                    Some(ident) => {
                        if let Some(ref ns) = ident.fq().0 {
                            ns == &self.primary_namespace
                        } else {
                            true
                        }
                    }
                    None => true,
                }
            })
            .collect())
    }

    // Validates that the constants are of the right type.
    fn validate_constants(&self) -> Result<(), ParseError> {
        // Search ast for constants.
        for (ty, constant) in
            self.namespaces.iter().flat_map(|(_, decls)| decls.iter()).filter_map(|decl| match decl
            {
                Decl::Constant { ty, value, .. } => Some((ty, value)),
                _ => None,
            })
        {
            let Constant(string) = constant;
            if string.len() > 2
                && (string.get(0..2) == Some("0x") || string.get(0..2) == Some("0b"))
            {
                // TODO(bwb): validate constants if hex as well
                return Ok(());
            }
            match ty {
                Ty::Int8 => {
                    i8::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::Int16 => {
                    i16::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::Int32 => {
                    i32::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::Int64 => {
                    i64::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::UInt8 => {
                    u8::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::UInt16 => {
                    u16::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::UInt32 | Ty::UInt64 => {
                    u32::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::Bool => {
                    bool::from_str(string)
                        .map_err(|_| ParseError::InvalidConstType(constant.clone(), ty.clone()))?;
                }
                Ty::Str { .. } => {
                    if !string.starts_with("\"") || !string.ends_with("\"") {
                        return Err(ParseError::InvalidConstType(constant.clone(), ty.clone()));
                    }
                }
                Ty::Identifier { id, .. } => {
                    let ident = Ident::new_raw(string);
                    // Special case: enum references "Enum.foo".
                    if let Some(ns) = &ident.namespace {
                        if ns == &id.name {
                            // The constant is a reference to an enum variant.
                            continue;
                        }
                    }
                    return Err(ParseError::InvalidConstType(constant.clone(), ty.clone()));
                }
                _ => {
                    return Err(ParseError::InvalidConstType(constant.clone(), ty.clone()));
                }
            };
        }

        // TODO(surajmalhotra): Find every bound array, string, and validate their bound is a valid
        // usize.
        Ok(())
    }

    pub fn parse(pair_vec: Vec<Pairs<'_, Rule>>) -> Result<Self, ParseError> {
        let mut primary_namespace = None;
        let mut namespaces = BTreeMap::default();

        let mut placeholder_generator = PlaceholderGenerator::new();

        for pairs in pair_vec {
            for pair in pairs {
                let mut current_namespace = String::default();
                for inner_pair in pair.into_inner() {
                    match inner_pair.as_rule() {
                        Rule::library_header => {
                            for token in inner_pair.into_inner() {
                                if Rule::compound_ident == token.as_rule() {
                                    current_namespace = String::from(token.as_str());
                                    // Keep updating the primary namespace as it should be the last
                                    // one we encounter.
                                    primary_namespace = Some(String::from(token.as_str()));
                                    if !namespaces.contains_key(&current_namespace) {
                                        namespaces
                                            .insert(current_namespace.clone(), Vec::default());
                                    }
                                }
                            }
                        }
                        Rule::using => {
                            for (cnt, pair) in inner_pair.into_inner().enumerate() {
                                if cnt == 0 {
                                    if !namespaces.contains_key(pair.as_str()) {
                                        return Err(ParseError::UnImported(format!(
                                            "{}",
                                            pair.as_str()
                                        )));
                                    }
                                } else {
                                    return Err(ParseError::NotYetSupported(String::from(
                                        "'as' in library imports",
                                    )));
                                }
                            }
                        }
                        Rule::struct_declaration
                        | Rule::union_declaration
                        | Rule::enum_declaration
                        | Rule::protocol_declaration
                        | Rule::const_declaration
                        | Rule::resource_declaration
                        | Rule::using_decl
                        | Rule::alias_declaration => {
                            let mut decls = Self::parse_decl(
                                inner_pair,
                                &current_namespace,
                                &namespaces,
                                &mut placeholder_generator,
                            )?;
                            namespaces.get_mut(&current_namespace).unwrap().append(&mut decls)
                        }
                        Rule::EOI => (),
                        e => return Err(ParseError::UnexpectedToken(e)),
                    };
                }
            }
        }

        let ast =
            BanjoAst { primary_namespace: primary_namespace.unwrap(), namespaces: namespaces };

        let _ = ast.validate_declaration_deps()?;
        ast.validate_constants()?;

        Ok(ast)
    }
}
