use proc_macro2::{Span, TokenStream};
use quote::{ToTokens, TokenStreamExt};
use syn::{Ident, Path};

/// Wrapper around strings to allow better interaction with attributes
// See serde_derive/src/internals/symbol.rs for 'inspiration'
#[derive(Debug)]
pub struct Symbol(pub &'static str);

/// The name of all attributes used by this derive crate
pub const JADED: Symbol = Symbol("jaded");

/// The java field to read from when deserializing
pub const FIELD_NAME: Symbol = Symbol("field");
/// The method to use when extracting custom data
pub const EXTRACT: Symbol = Symbol("extract");

/// Whether to rename all fields to match the camelCase Java convention
pub const RENAME: Symbol = Symbol("rename");
/// The FQCN to check when deserializing a Java object
pub const CLASS: Symbol = Symbol("class");
/// The detour to take when deserializing an object
pub const FROM: Symbol = Symbol("from");

impl PartialEq<Symbol> for Ident {
    fn eq(&self, word: &Symbol) -> bool {
        self == word.0
    }
}

impl<'a> PartialEq<Symbol> for &'a Ident {
    fn eq(&self, word: &Symbol) -> bool {
        *self == word.0
    }
}

impl PartialEq<Symbol> for Path {
    fn eq(&self, word: &Symbol) -> bool {
        self.is_ident(word.0)
    }
}

impl<'a> PartialEq<Symbol> for &'a Path {
    fn eq(&self, word: &Symbol) -> bool {
        self.is_ident(word.0)
    }
}

impl ToTokens for Symbol {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(Ident::new(self.0, Span::call_site()));
    }
}
