# Path: pytaxize/refactor.py
# class Refactor:
#     def __init__(self, url, payload={}, request="get"):
#         self.url = url
#         self.payload = payload
#         self.request = request
# 
#     def return_requests(self, **kwargs):
#         if self.request == "get":
#             return requests.get(self.url, params=self.payload, **kwargs)
#         else:
#             return requests.post(self.url, params=self.payload, **kwargs)
# 
#     def xml(self, **kwargs):
#         if self.request == "get":
#             out = requests.get(self.url, params=self.payload, **kwargs)
#             out.raise_for_status()
#             xmlparser = etree.XMLParser()
#             tt = etree.fromstring(out.content, xmlparser)
#             try:
#                 # If entrez api 'X-RateLimit-Remaining' header is 1 or below, pause for a second to allow rate limit to reset
#                 if (int(out.headers['X-RateLimit-Remaining'])<=1):
#                     time.sleep(1)
#             except:
#                 pass 
#             return tt
#         else:
#             out = requests.post(self.url, params=self.payload, **kwargs)
#             out.raise_for_status()
#             xmlparser = etree.XMLParser()
#             tt = etree.fromstring(out.content, xmlparser)
#             return tt
# 
#     def json(self, **kwargs):
#         if self.request == "get":
#             out = requests.get(self.url, params=self.payload, **kwargs)
#             out.raise_for_status()
#             return out.json()
#         else:
#             out = requests.post(self.url, params=self.payload, **kwargs)
#             out.raise_for_status()
#             return out.json()
# 
#     def raw(self, **kwargs):
#         if self.request == "get":
#             out = requests.get(self.url, params=self.payload, **kwargs)
#             out.raise_for_status()
#             return out.text
#         else:
#             out = requests.post(self.url, params=self.payload, **kwargs)
#             out.raise_for_status()
#             return out.text


import os
import requests
import datetime
import re
import json
import pkg_resources
    import doctest
from lxml import etree
from pytaxize.refactor import Refactor
from pytaxize.utils import *

    Usage::

        from pytaxize import ncbi
        ncbi.hierarchy(ids=9606)
        ncbi.hierarchy(ids=[9606,55062,4231])
    """
    toget = ["ScientificName", "Rank", "TaxId"]
    key = os.environ.get("ENTREZ_KEY")
    if key is None:
        raise Exception("ENTREZ_KEY is not defined")
    if not isinstance(ids, list):
        ids = [ids]
    idz = ",".join([str(x) for x in ids])
    args = {"db": "taxonomy", "ID": idz, "api_key": key}
    res = _entrez("efetch", args)
    taxa = res.xpath("//TaxaSet/Taxon")
    out = []
    for x in range(len(taxa)):
        nodes = taxa[x].xpath(".//LineageEx/Taxon")
        tmp = [
            dict(zip(toget, [node.xpath(w)[0].text for w in toget])) for node in nodes
        ]
        tmp.append(dict(zip(toget, [taxa[x].xpath(w)[0].text for w in toget])))
        out.append(tmp)
    return dict(zip(ids, out))


def _entrez(path="esearch", args={}):
    url = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/%s.fcgi" % path

# Path: pytaxize/refactor.py
# class Refactor:
#     def __init__(self, url, payload={}, request="get"):
#         self.url = url
#         self.payload = payload
#         self.request = request
# 
#     def return_requests(self, **kwargs):
#         if self.request == "get":
#             return requests.get(self.url, params=self.payload, **kwargs)
#         else:
#             return requests.post(self.url, params=self.payload, **kwargs)
# 
#     def xml(self, **kwargs):
#         if self.request == "get":
#             out = requests.get(self.url, params=self.payload, **kwargs)
#             out.raise_for_status()
#             xmlparser = etree.XMLParser()
#             tt = etree.fromstring(out.content, xmlparser)
#             try:
#                 # If entrez api 'X-RateLimit-Remaining' header is 1 or below, pause for a second to allow rate limit to reset
#                 if (int(out.headers['X-RateLimit-Remaining'])<=1):
#                     time.sleep(1)
#             except:
#                 pass 
#             return tt
#         else:
#             out = requests.post(self.url, params=self.payload, **kwargs)
#             out.raise_for_status()
#             xmlparser = etree.XMLParser()
#             tt = etree.fromstring(out.content, xmlparser)
#             return tt
# 
#     def json(self, **kwargs):
#         if self.request == "get":
#             out = requests.get(self.url, params=self.payload, **kwargs)
#             out.raise_for_status()
#             return out.json()
#         else:
#             out = requests.post(self.url, params=self.payload, **kwargs)
#             out.raise_for_status()
#             return out.json()
# 
#     def raw(self, **kwargs):
#         if self.request == "get":
#             out = requests.get(self.url, params=self.payload, **kwargs)
#             out.raise_for_status()
#             return out.text
#         else:
#             out = requests.post(self.url, params=self.payload, **kwargs)
#             out.raise_for_status()
#             return out.text


# Path: pytaxize/ncbi/ncbi.py
import os
import requests
import datetime
import re
import json
import pkg_resources
    import doctest
from lxml import etree
from pytaxize.refactor import Refactor
from pytaxize.utils import *


    Usage::

        from pytaxize import ncbi
        ncbi.hierarchy(ids=9606)
        ncbi.hierarchy(ids=[9606,55062,4231])
    """
    toget = ["ScientificName", "Rank", "TaxId"]
    key = os.environ.get("ENTREZ_KEY")
    if key is None:
        raise Exception("ENTREZ_KEY is not defined")
    if not isinstance(ids, list):
        ids = [ids]
    idz = ",".join([str(x) for x in ids])
    args = {"db": "taxonomy", "ID": idz, "api_key": key}
    res = _entrez("efetch", args)
    taxa = res.xpath("//TaxaSet/Taxon")
    out = []
    for x in range(len(taxa)):
        nodes = taxa[x].xpath(".//LineageEx/Taxon")
        tmp = [
            dict(zip(toget, [node.xpath(w)[0].text for w in toget])) for node in nodes
        ]
        tmp.append(dict(zip(toget, [taxa[x].xpath(w)[0].text for w in toget])))
        out.append(tmp)
    return dict(zip(ids, out))


def _entrez(path="esearch", args={}):
    url = "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/%s.fcgi" % path

    tt = Refactor(url, args, request="get").xml()