//! Things to wrap other things in file ids.
use std::borrow::Borrow;

use either::Either;
use span::{AstIdNode, ErasedFileAstId, FileAstId, FileId, SyntaxContext};
use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextSize};

use crate::{
    EditionedFileId, HirFileId, MacroCallId, MacroKind,
    db::{self, ExpandDatabase},
    map_node_range_up, map_node_range_up_rooted, span_for_offset,
};

/// `InFile<T>` stores a value of `T` inside a particular file/syntax tree.
///
/// Typical usages are:
///
/// * `InFile<SyntaxNode>` -- syntax node in a file
/// * `InFile<ast::FnDef>` -- ast node in a file
/// * `InFile<TextSize>` -- offset in a file
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub struct InFileWrapper<FileKind, T> {
    pub file_id: FileKind,
    pub value: T,
}
pub type InFile<T> = InFileWrapper<HirFileId, T>;
pub type InMacroFile<T> = InFileWrapper<MacroCallId, T>;
pub type InRealFile<T> = InFileWrapper<EditionedFileId, T>;

#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub struct FilePositionWrapper<FileKind> {
    pub file_id: FileKind,
    pub offset: TextSize,
}
pub type HirFilePosition = FilePositionWrapper<HirFileId>;
pub type MacroFilePosition = FilePositionWrapper<MacroCallId>;
pub type FilePosition = FilePositionWrapper<EditionedFileId>;

impl FilePosition {
    #[inline]
    pub fn into_file_id(self, db: &dyn ExpandDatabase) -> FilePositionWrapper<FileId> {
        FilePositionWrapper { file_id: self.file_id.file_id(db), offset: self.offset }
    }
}

impl From<FileRange> for HirFileRange {
    fn from(value: FileRange) -> Self {
        HirFileRange { file_id: value.file_id.into(), range: value.range }
    }
}

impl From<FilePosition> for HirFilePosition {
    fn from(value: FilePosition) -> Self {
        HirFilePosition { file_id: value.file_id.into(), offset: value.offset }
    }
}

impl FilePositionWrapper<span::FileId> {
    pub fn with_edition(self, db: &dyn ExpandDatabase, edition: span::Edition) -> FilePosition {
        FilePositionWrapper {
            file_id: EditionedFileId::new(db, self.file_id, edition),
            offset: self.offset,
        }
    }
}

impl FileRangeWrapper<span::FileId> {
    pub fn with_edition(self, db: &dyn ExpandDatabase, edition: span::Edition) -> FileRange {
        FileRangeWrapper {
            file_id: EditionedFileId::new(db, self.file_id, edition),
            range: self.range,
        }
    }
}

impl<T> InFileWrapper<span::FileId, T> {
    pub fn with_edition(self, db: &dyn ExpandDatabase, edition: span::Edition) -> InRealFile<T> {
        InRealFile { file_id: EditionedFileId::new(db, self.file_id, edition), value: self.value }
    }
}

impl HirFileRange {
    pub fn file_range(self) -> Option<FileRange> {
        Some(FileRange { file_id: self.file_id.file_id()?, range: self.range })
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub struct FileRangeWrapper<FileKind> {
    pub file_id: FileKind,
    pub range: TextRange,
}
pub type HirFileRange = FileRangeWrapper<HirFileId>;
pub type MacroFileRange = FileRangeWrapper<MacroCallId>;
pub type FileRange = FileRangeWrapper<EditionedFileId>;

impl FileRange {
    #[inline]
    pub fn into_file_id(self, db: &dyn ExpandDatabase) -> FileRangeWrapper<FileId> {
        FileRangeWrapper { file_id: self.file_id.file_id(db), range: self.range }
    }

    #[inline]
    pub fn file_text(self, db: &dyn ExpandDatabase) -> &triomphe::Arc<str> {
        db.file_text(self.file_id.file_id(db)).text(db)
    }

    #[inline]
    pub fn text(self, db: &dyn ExpandDatabase) -> &str {
        &self.file_text(db)[self.range]
    }
}

/// `AstId` points to an AST node in any file.
///
/// It is stable across reparses, and can be used as salsa key/value.
pub type AstId<N> = crate::InFile<FileAstId<N>>;

impl<N: AstNode> AstId<N> {
    pub fn to_node(&self, db: &dyn ExpandDatabase) -> N {
        self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id))
    }
    pub fn to_range(&self, db: &dyn ExpandDatabase) -> TextRange {
        self.to_ptr(db).text_range()
    }
    pub fn to_in_file_node(&self, db: &dyn ExpandDatabase) -> crate::InFile<N> {
        crate::InFile::new(self.file_id, self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id)))
    }
    pub fn to_ptr(&self, db: &dyn ExpandDatabase) -> AstPtr<N> {
        db.ast_id_map(self.file_id).get(self.value)
    }
    pub fn erase(&self) -> ErasedAstId {
        crate::InFile::new(self.file_id, self.value.erase())
    }
    #[inline]
    pub fn upcast<M: AstIdNode>(self) -> AstId<M>
    where
        N: Into<M>,
    {
        self.map(|it| it.upcast())
    }
}

pub type ErasedAstId = crate::InFile<ErasedFileAstId>;

impl ErasedAstId {
    pub fn to_range(&self, db: &dyn ExpandDatabase) -> TextRange {
        self.to_ptr(db).text_range()
    }
    pub fn to_ptr(&self, db: &dyn ExpandDatabase) -> SyntaxNodePtr {
        db.ast_id_map(self.file_id).get_erased(self.value)
    }
}

impl<FileKind, T> InFileWrapper<FileKind, T> {
    pub fn new(file_id: FileKind, value: T) -> Self {
        Self { file_id, value }
    }

    pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> InFileWrapper<FileKind, U> {
        InFileWrapper::new(self.file_id, f(self.value))
    }
}

impl<FileKind: Copy, T> InFileWrapper<FileKind, T> {
    pub fn with_value<U>(&self, value: U) -> InFileWrapper<FileKind, U> {
        InFileWrapper::new(self.file_id, value)
    }

    pub fn as_ref(&self) -> InFileWrapper<FileKind, &T> {
        self.with_value(&self.value)
    }

    pub fn borrow<U>(&self) -> InFileWrapper<FileKind, &U>
    where
        T: Borrow<U>,
    {
        self.with_value(self.value.borrow())
    }
}

impl<FileKind: Copy, T: Clone> InFileWrapper<FileKind, &T> {
    pub fn cloned(&self) -> InFileWrapper<FileKind, T> {
        self.with_value(self.value.clone())
    }
}

impl<T> From<InMacroFile<T>> for InFile<T> {
    fn from(InMacroFile { file_id, value }: InMacroFile<T>) -> Self {
        InFile { file_id: file_id.into(), value }
    }
}

impl<T> From<InRealFile<T>> for InFile<T> {
    fn from(InRealFile { file_id, value }: InRealFile<T>) -> Self {
        InFile { file_id: file_id.into(), value }
    }
}

// region:transpose impls

impl<FileKind, T> InFileWrapper<FileKind, Option<T>> {
    pub fn transpose(self) -> Option<InFileWrapper<FileKind, T>> {
        Some(InFileWrapper::new(self.file_id, self.value?))
    }
}

impl<FileKind, L, R> InFileWrapper<FileKind, Either<L, R>> {
    pub fn transpose(self) -> Either<InFileWrapper<FileKind, L>, InFileWrapper<FileKind, R>> {
        match self.value {
            Either::Left(l) => Either::Left(InFileWrapper::new(self.file_id, l)),
            Either::Right(r) => Either::Right(InFileWrapper::new(self.file_id, r)),
        }
    }
}

// endregion:transpose impls

trait FileIdToSyntax: Copy {
    fn file_syntax(self, db: &dyn db::ExpandDatabase) -> SyntaxNode;
}

impl FileIdToSyntax for EditionedFileId {
    fn file_syntax(self, db: &dyn db::ExpandDatabase) -> SyntaxNode {
        db.parse(self).syntax_node()
    }
}
impl FileIdToSyntax for MacroCallId {
    fn file_syntax(self, db: &dyn db::ExpandDatabase) -> SyntaxNode {
        db.parse_macro_expansion(self).value.0.syntax_node()
    }
}
impl FileIdToSyntax for HirFileId {
    fn file_syntax(self, db: &dyn db::ExpandDatabase) -> SyntaxNode {
        db.parse_or_expand(self)
    }
}

#[allow(private_bounds)]
impl<FileId: FileIdToSyntax, T> InFileWrapper<FileId, T> {
    pub fn file_syntax(&self, db: &dyn db::ExpandDatabase) -> SyntaxNode {
        FileIdToSyntax::file_syntax(self.file_id, db)
    }
}

#[allow(private_bounds)]
impl<FileId: FileIdToSyntax, N: AstNode> InFileWrapper<FileId, AstPtr<N>> {
    pub fn to_node(&self, db: &dyn ExpandDatabase) -> N {
        self.value.to_node(&self.file_syntax(db))
    }
}

impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, N> {
    pub fn syntax(&self) -> InFileWrapper<FileId, &SyntaxNode> {
        self.with_value(self.value.syntax())
    }
    pub fn node_file_range(&self) -> FileRangeWrapper<FileId> {
        FileRangeWrapper { file_id: self.file_id, range: self.value.syntax().text_range() }
    }
}

impl<FileId: Copy, N: AstNode> InFileWrapper<FileId, &N> {
    // unfortunately `syntax` collides with the impl above, because `&_` is fundamental
    pub fn syntax_ref(&self) -> InFileWrapper<FileId, &SyntaxNode> {
        self.with_value(self.value.syntax())
    }
}

// region:specific impls
impl<FileId: Copy, SN: Borrow<SyntaxNode>> InFileWrapper<FileId, SN> {
    pub fn file_range(&self) -> FileRangeWrapper<FileId> {
        FileRangeWrapper { file_id: self.file_id, range: self.value.borrow().text_range() }
    }
}

impl<SN: Borrow<SyntaxNode>> InFile<SN> {
    pub fn parent_ancestors_with_macros(
        self,
        db: &dyn db::ExpandDatabase,
    ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
        let succ = move |node: &InFile<SyntaxNode>| match node.value.parent() {
            Some(parent) => Some(node.with_value(parent)),
            None => db
                .lookup_intern_macro_call(node.file_id.macro_file()?)
                .to_node_item(db)
                .syntax()
                .cloned()
                .map(|node| node.parent())
                .transpose(),
        };
        std::iter::successors(succ(&self.borrow().cloned()), succ)
    }

    pub fn ancestors_with_macros(
        self,
        db: &dyn db::ExpandDatabase,
    ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
        let succ = move |node: &InFile<SyntaxNode>| match node.value.parent() {
            Some(parent) => Some(node.with_value(parent)),
            None => db
                .lookup_intern_macro_call(node.file_id.macro_file()?)
                .to_node_item(db)
                .syntax()
                .cloned()
                .map(|node| node.parent())
                .transpose(),
        };
        std::iter::successors(Some(self.borrow().cloned()), succ)
    }

    pub fn kind(&self) -> parser::SyntaxKind {
        self.value.borrow().kind()
    }

    pub fn text_range(&self) -> TextRange {
        self.value.borrow().text_range()
    }

    /// Falls back to the macro call range if the node cannot be mapped up fully.
    ///
    /// For attributes and derives, this will point back to the attribute only.
    /// For the entire item use [`InFile::original_file_range_full`].
    pub fn original_file_range_rooted(self, db: &dyn db::ExpandDatabase) -> FileRange {
        self.borrow().map(SyntaxNode::text_range).original_node_file_range_rooted(db)
    }

    /// Falls back to the macro call range if the node cannot be mapped up fully.
    pub fn original_file_range_with_macro_call_input(
        self,
        db: &dyn db::ExpandDatabase,
    ) -> FileRange {
        self.borrow().map(SyntaxNode::text_range).original_node_file_range_with_macro_call_input(db)
    }

    pub fn original_syntax_node_rooted(
        self,
        db: &dyn db::ExpandDatabase,
    ) -> Option<InRealFile<SyntaxNode>> {
        // This kind of upmapping can only be achieved in attribute expanded files,
        // as we don't have node inputs otherwise and therefore can't find an `N` node in the input
        let file_id = match self.file_id {
            HirFileId::FileId(file_id) => {
                return Some(InRealFile { file_id, value: self.value.borrow().clone() });
            }
            HirFileId::MacroFile(m)
                if matches!(m.kind(db), MacroKind::Attr | MacroKind::AttrBuiltIn) =>
            {
                m
            }
            _ => return None,
        };

        let FileRange { file_id: editioned_file_id, range } = map_node_range_up_rooted(
            db,
            &db.expansion_span_map(file_id),
            self.value.borrow().text_range(),
        )?;

        let kind = self.kind();
        let value = db
            .parse(editioned_file_id)
            .syntax_node()
            .covering_element(range)
            .ancestors()
            .take_while(|it| it.text_range() == range)
            .find(|it| it.kind() == kind)?;
        Some(InRealFile::new(editioned_file_id, value))
    }
}

impl InFile<&SyntaxNode> {
    /// Attempts to map the syntax node back up its macro calls.
    pub fn original_file_range_opt(
        self,
        db: &dyn db::ExpandDatabase,
    ) -> Option<(FileRange, SyntaxContext)> {
        self.borrow().map(SyntaxNode::text_range).original_node_file_range_opt(db)
    }
}

impl InMacroFile<SyntaxToken> {
    pub fn upmap_once(
        self,
        db: &dyn db::ExpandDatabase,
    ) -> InFile<smallvec::SmallVec<[TextRange; 1]>> {
        self.file_id.expansion_info(db).map_range_up_once(db, self.value.text_range())
    }
}

impl InFile<SyntaxToken> {
    /// Falls back to the macro call range if the node cannot be mapped up fully.
    pub fn original_file_range(self, db: &dyn db::ExpandDatabase) -> FileRange {
        match self.file_id {
            HirFileId::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
            HirFileId::MacroFile(mac_file) => {
                let (range, ctxt) = span_for_offset(
                    db,
                    &db.expansion_span_map(mac_file),
                    self.value.text_range().start(),
                );

                // FIXME: Figure out an API that makes proper use of ctx, this only exists to
                // keep pre-token map rewrite behaviour.
                if ctxt.is_root() {
                    return range;
                }

                // Fall back to whole macro call.
                let loc = db.lookup_intern_macro_call(mac_file);
                loc.kind.original_call_range(db)
            }
        }
    }

    /// Attempts to map the syntax node back up its macro calls.
    pub fn original_file_range_opt(self, db: &dyn db::ExpandDatabase) -> Option<FileRange> {
        match self.file_id {
            HirFileId::FileId(file_id) => {
                Some(FileRange { file_id, range: self.value.text_range() })
            }
            HirFileId::MacroFile(mac_file) => {
                let (range, ctxt) = span_for_offset(
                    db,
                    &db.expansion_span_map(mac_file),
                    self.value.text_range().start(),
                );

                // FIXME: Figure out an API that makes proper use of ctx, this only exists to
                // keep pre-token map rewrite behaviour.
                if ctxt.is_root() { Some(range) } else { None }
            }
        }
    }
}

impl InMacroFile<TextSize> {
    pub fn original_file_range(self, db: &dyn db::ExpandDatabase) -> (FileRange, SyntaxContext) {
        span_for_offset(db, &db.expansion_span_map(self.file_id), self.value)
    }
}

impl InFile<TextRange> {
    pub fn original_node_file_range(
        self,
        db: &dyn db::ExpandDatabase,
    ) -> (FileRange, SyntaxContext) {
        match self.file_id {
            HirFileId::FileId(file_id) => {
                (FileRange { file_id, range: self.value }, SyntaxContext::root(file_id.edition(db)))
            }
            HirFileId::MacroFile(mac_file) => {
                match map_node_range_up(db, &db.expansion_span_map(mac_file), self.value) {
                    Some(it) => it,
                    None => {
                        let loc = db.lookup_intern_macro_call(mac_file);
                        (loc.kind.original_call_range(db), SyntaxContext::root(loc.def.edition))
                    }
                }
            }
        }
    }

    pub fn original_node_file_range_rooted(self, db: &dyn db::ExpandDatabase) -> FileRange {
        match self.file_id {
            HirFileId::FileId(file_id) => FileRange { file_id, range: self.value },
            HirFileId::MacroFile(mac_file) => {
                match map_node_range_up_rooted(db, &db.expansion_span_map(mac_file), self.value) {
                    Some(it) => it,
                    _ => {
                        let loc = db.lookup_intern_macro_call(mac_file);
                        loc.kind.original_call_range(db)
                    }
                }
            }
        }
    }

    pub fn original_node_file_range_with_macro_call_input(
        self,
        db: &dyn db::ExpandDatabase,
    ) -> FileRange {
        match self.file_id {
            HirFileId::FileId(file_id) => FileRange { file_id, range: self.value },
            HirFileId::MacroFile(mac_file) => {
                match map_node_range_up_rooted(db, &db.expansion_span_map(mac_file), self.value) {
                    Some(it) => it,
                    _ => {
                        let loc = db.lookup_intern_macro_call(mac_file);
                        loc.kind.original_call_range_with_input(db)
                    }
                }
            }
        }
    }

    pub fn original_node_file_range_opt(
        self,
        db: &dyn db::ExpandDatabase,
    ) -> Option<(FileRange, SyntaxContext)> {
        match self.file_id {
            HirFileId::FileId(file_id) => Some((
                FileRange { file_id, range: self.value },
                SyntaxContext::root(file_id.edition(db)),
            )),
            HirFileId::MacroFile(mac_file) => {
                map_node_range_up(db, &db.expansion_span_map(mac_file), self.value)
            }
        }
    }

    pub fn original_node_file_range_rooted_opt(
        self,
        db: &dyn db::ExpandDatabase,
    ) -> Option<FileRange> {
        match self.file_id {
            HirFileId::FileId(file_id) => Some(FileRange { file_id, range: self.value }),
            HirFileId::MacroFile(mac_file) => {
                map_node_range_up_rooted(db, &db.expansion_span_map(mac_file), self.value)
            }
        }
    }
}

impl<N: AstNode> InFile<N> {
    pub fn original_ast_node_rooted(self, db: &dyn db::ExpandDatabase) -> Option<InRealFile<N>> {
        // This kind of upmapping can only be achieved in attribute expanded files,
        // as we don't have node inputs otherwise and therefore can't find an `N` node in the input
        let file_id = match self.file_id {
            HirFileId::FileId(file_id) => {
                return Some(InRealFile { file_id, value: self.value });
            }
            HirFileId::MacroFile(m) => m,
        };
        if !matches!(file_id.kind(db), MacroKind::Attr | MacroKind::AttrBuiltIn) {
            return None;
        }

        let FileRange { file_id: editioned_file_id, range } = map_node_range_up_rooted(
            db,
            &db.expansion_span_map(file_id),
            self.value.syntax().text_range(),
        )?;

        // FIXME: This heuristic is brittle and with the right macro may select completely unrelated nodes?
        let anc = db.parse(editioned_file_id).syntax_node().covering_element(range);
        let value = anc.ancestors().find_map(N::cast)?;
        Some(InRealFile::new(editioned_file_id, value))
    }
}

impl<T> InFile<T> {
    pub fn into_real_file(self) -> Result<InRealFile<T>, InFile<T>> {
        match self.file_id {
            HirFileId::FileId(file_id) => Ok(InRealFile { file_id, value: self.value }),
            HirFileId::MacroFile(_) => Err(self),
        }
    }
}
