import re
import logging
from indra.resources import load_resource_json


logger = logging.getLogger(__name__)


identifiers_url = 'https://identifiers.org'

# These are just special cases of name spaces where the mapping from INDRA to
# identifiers.org is not a question of simplecapitalization.
identifiers_mappings = {
    'UP': 'uniprot',
    'UPPRO': 'uniprot.chain',
    'UPISO': 'uniprot.isoform',
    'REFSEQ_PROT': 'refseq',
    'PF': 'pfam',
    'IP': 'interpro',
    'ECCODE': 'ec-code',
    'NONCODE': 'noncodev4.rna',
    'LNCRNADB': 'rnacentral',
    'MIRBASEM': 'mirbase.mature',
    'EGID': 'ncbigene',
    'NCBI': 'ncibgene',
    'HGNC_GROUP': 'hgnc.genefamily',
    'LINCS': 'lincs.smallmolecule',
    'PUBCHEM': 'pubchem.compound',
    'CHEMBL': 'chembl.compound',
    'CTD': 'ctd.chemical',
    'CVCL': 'cellosaurus',
}

# These are namespaces used by INDRA that don't have corresponding
# identifiers.org entries
non_registry = {
    'SDIS', 'SCHEM', 'SFAM', 'SCOMP', 'SIGNOR', 'HMS-LINCS', 'NXPFA',
    'OMIM', 'LSPCI', 'UPLOC', 'BFO', 'CCLE'
}

# These are namespaces that can appear in db_refs but are actually not
# representing grounding.
non_grounding = {
    'TEXT', 'TEXT_NORM'
}

# These are reverse mappings from identifiers.org namespaces to INDRA
# namespaces
identifiers_reverse = {
    v: k for k, v in identifiers_mappings.items()
}
# We have to patch this one because it is ambiguous
identifiers_reverse['ncbigene'] = 'EGID'

# These are only the URLs that are strictly prefixes and not more complicated
# patterns. This is because some downstream code uses these as prefixes
# rather than arbitrary patterns.
url_prefixes = {
    # Biology namespaces
    'NXPFA': 'https://www.nextprot.org/term/FA-',
    'SIGNOR': 'https://signor.uniroma2.it/relation_result.php?id=',
    'LSPCI': 'https://labsyspharm.github.io/lspci/',
    # WM namespaces
    'UN': 'https://github.com/clulab/eidos/wiki/JSON-LD#Grounding/',
    'WDI': 'https://github.com/clulab/eidos/wiki/JSON-LD#Grounding/',
    'FAO': 'https://github.com/clulab/eidos/wiki/JSON-LD#Grounding/',
    'HUME': ('https://github.com/BBN-E/Hume/blob/master/resource/ontologies'
             '/hume_ontology/'),
    'CWMS': 'http://trips.ihmc.us/',
    'SOFIA': 'http://cs.cmu.edu/sofia/',
}


def get_ns_from_identifiers(identifiers_ns):
    """"Return a namespace compatible with INDRA from an identifiers namespace.

    For example, this function can be used to map 'uniprot' to 'UP'.

    Parameters
    ----------
    identifiers_ns : str
        An identifiers.org standard namespace.

    Returns
    -------
    str or None
        The namespace compatible with INDRA's internal representation or
        None if the given namespace isn't an identifiers.org standard.
    """
    reg_entry = identifiers_registry.get(identifiers_ns.lower())
    if not reg_entry:
        return None
    mapping = identifiers_reverse.get(identifiers_ns.lower())
    if mapping:
        return mapping
    else:
        return identifiers_ns.upper()


def get_ns_id_from_identifiers(identifiers_ns, identifiers_id):
    """Return a namespace/ID pair compatible with INDRA from identifiers.

    Parameters
    ----------
    identifiers_ns : str
        An identifiers.org standard namespace.
    identifiers_id : str
        An identifiers.org standard ID in the given namespace.

    Returns
    -------
    (str, str)
        A namespace and ID that are valid in INDRA db_refs.
    """
    reg_entry = identifiers_registry.get(identifiers_ns.lower())
    db_ns = get_ns_from_identifiers(identifiers_ns)
    if db_ns is None:
        return None, None
    db_id = identifiers_id
    if reg_entry['namespace_embedded']:
        if not identifiers_id.startswith(identifiers_ns.upper()):
            db_id = '%s:%s' % (identifiers_ns.upper(), identifiers_id)
    return db_ns, db_id