import argparse
import json
import os
import sys
import traceback
import urllib.request
from collections import defaultdict, Counter
from datetime import datetime
from itertools import chain
from time import gmtime, strftime, sleep

import requests
from tqdm import tqdm

from scheduled_bots import utils, PROPS
from wikidataintegrator import wdi_core, wdi_helpers, wdi_login, wdi_property_store
from wikidataintegrator.ref_handlers import update_retrieved_if_new
from wikidataintegrator.wdi_helpers import id_mapper

try:
    from scheduled_bots.local import WDUSER, WDPASS
except ImportError:
    if "WDUSER" in os.environ and "WDPASS" in os.environ:
        WDUSER = os.environ['WDUSER']
        WDPASS = os.environ['WDPASS']
    else:
        raise ValueError("WDUSER and WDPASS must be specified in local.py or as environment variables")



wdi_property_store.wd_properties[PROPS['OMIM ID']]['core_id'] = False
#wdi_property_store.wd_properties[PROPS['MeSH ID']]['core_id'] = False
wdi_property_store.wd_properties[PROPS['Orphanet ID']]['core_id'] = False
wdi_property_store.wd_properties[PROPS['NCI Thesaurus ID']]['core_id'] = False

__metadata__ = {'name': 'DOIDBot',
                'tags': ['disease', 'doid'],
                'properties': list(PROPS.values())
                }


class DOGraph:
    edge_prop = {
        # 'http://purl.obolibrary.org/obo/IDO_0000664': 'P828',  # has_material_basis_in -> has cause
        'http://purl.obolibrary.org/obo/RO_0001025': 'P276',  # located in
        # 'http://purl.obolibrary.org/obo/RO_0002451': None,  # transmitted by. "pathogen transmission process" (P1060)?
        'is_a': 'P279'}

    xref_prop = {'ORDO': 'P1550',
                 'UMLS_CUI': 'P2892',
                 'DOID': 'P699',
                 'ICD10CM': 'P4229',
                 'ICD10': 'P494',
                 'ICD9CM': 'P1692',
                 'ICD9': 'P493',
                  #'MSH': 'P486',
                  #             'MESH': 'P486',
                 'NCI': 'P1748',
                 'OMIM': 'P492',
                 # 'SNOMEDCT_US_2016_03_01': ''  # can't put in wikidata...
                 }
    purl_wdid = dict()

    def get_existing_items(self):
        # get all existing items we can add relationships to
        doid_wdid = id_mapper('P699')
        self.purl_wdid = {"http://purl.obolibrary.org/obo/{}".format(k.replace(":", "_")): v for k, v in
                          doid_wdid.items()}
        # add in uberon items so we can do "located in"
        uberon_wdid = id_mapper('P1554')
        self.purl_wdid.update({"http://purl.obolibrary.org/obo/UBERON_{}".format(k): v for k, v in uberon_wdid.items()})
        # add in taxonomy items for "has_material_basis_in"
        ncbi_wdid = id_mapper("P685")
        self.purl_wdid.update(
            {"http://purl.obolibrary.org/obo/NCBITaxon_{}".format(k): v for k, v in ncbi_wdid.items()})

    def __init__(self, graph, login=None, fast_run=True):
        self.fast_run = fast_run
        self.version = None
        self.date = None
        self.default_namespace = None
        self.login = login
        self.nodes = dict()
        self.parse_meta(graph['meta'])
        self.parse_nodes(graph['nodes'])
        self.parse_edges(graph['edges'])
        self.dedupe_wikilinks()
        self.release = None
        if not self.purl_wdid:
            self.get_existing_items()

    def parse_meta(self, meta):
        self.version = meta['version']
        datestr = [x['val'] for x in meta['basicPropertyValues'] if
                   x['pred'] == 'http://www.geneontology.org/formats/oboInOwl#date'][0]
        self.date = datetime.strptime(datestr, '%d:%m:%Y %H:%M')
        self.default_namespace = [x['val'] for x in meta['basicPropertyValues'] if
                                  x['pred'] == 'http://www.geneontology.org/formats/oboInOwl#default-namespace'][0]

    def parse_nodes(self, nodes):
        for node in nodes:
            try:
                tmp_node = DONode(node, self)
                if "http://purl.obolibrary.org/obo/DOID_" in tmp_node.id and not tmp_node.deprecated and tmp_node.type == "CLASS":
                    self.nodes[tmp_node.id] = tmp_node
            except Exception as e:
                msg = wdi_helpers.format_msg(node['id'], 'P699', None, str(e), msg_type=type(e))
                wdi_core.WDItemEngine.log("ERROR", msg)

    def parse_edges(self, edges):
        for edge in edges:
            # don't add edges where the subject is a node not in this ontology
            if edge['sub'] not in self.nodes:
                continue
            self.nodes[edge['sub']].add_relationship(edge['pred'], edge['obj'])

    def create_release(self):
        r = wdi_helpers.Release('Disease Ontology release {}'.format(self.date.strftime('%Y-%m-%d')),
                                'Release of the Disease Ontology', self.date.strftime('%Y-%m-%d'),
                                archive_url=self.version, edition_of_wdid='Q5282129',
                                pub_date=self.date.date().strftime('+%Y-%m-%dT%H:%M:%SZ'))
        wd_item_id = r.get_or_create(self.login)
        if wd_item_id:
            self.release = wd_item_id
        else:
            raise ValueError("unable to create release")

    def create_ref_statement(self, doid):
        if not self.release:
            self.create_release()