from __future__ import absolute_import, print_function, unicode_literals
from builtins import dict, str
import logging
from indra.java_vm import autoclass, JavaException

try:
    # Python 3
    from urllib.request import urlopen
    from urllib.error import HTTPError
    from urllib.parse import urlencode
except ImportError:
    # Python 2
    from urllib2 import urlopen, HTTPError
    from urllib import urlencode

logger = logging.getLogger('biopax')

pc2_url = 'http://www.pathwaycommons.org/pc2/'

def graph_query(kind, source, target=None, neighbor_limit=1):
    """Perform a graph query on PathwayCommons.

    For more information on these queries, see
    http://www.pathwaycommons.org/pc2/#graph

    Parameters
    ----------
    kind : str
        The kind of graph query to perform. Currently 3 options are
        implemented, 'neighborhood', 'pathsbetween' and 'pathsfromto'.
    source : list[str]
        A list of gene names which are the source set for the graph query.
    target : Optional[list[str]]
        A list of gene names which are the target set for the graph query.
        Only needed for 'pathsfromto' queries.
    neighbor_limit : Optional[int]
        This limits the length of the longest path considered in
        the graph query. Default: 1

    Returns
    -------
    model : org.biopax.paxtools.model.Model
        A BioPAX model (java object).
    """
    params = {}
    params['format'] = 'BIOPAX'
    params['organism'] = '9606'
    # Get the "kind" string
    kind_str = kind.lower()
    if kind not in ['neighborhood', 'pathsbetween', 'pathsfromto']:
        logger.warn('Invalid query type %s' % kind_str)
        return None
    params['kind'] = kind_str
    # Get the source string
    if isinstance(source, str):
        source_str = source
    else:
        source_str = ','.join(source)
    params['source'] = source_str
    try:
        neighbor_limit = int(neighbor_limit)
    except (TypeError, ValueError):
        logger.warn('Invalid neighborhood limit %s' % neighbor_limit)
        return None
    if target is not None:
        if isinstance(target, str):
            target_str = target
        else:
            target_str = ','.join(target)
        params['target'] = target_str

    logger.info('Sending Pathway Commons query...')
    try:
        res = urlopen(pc2_url + 'graph', data=urlencode(params).encode('utf-8'))
    except HTTPError as e:
        logger.error('Response is HTTP eror code %d.' % e.code)
        return None

    # We don't decode to Unicode here because owl_str_to_model expects
    # a byte stream
    owl_str = res.read()
    model = owl_str_to_model(owl_str)
    if model is not None:
        logger.info('Pathway Commons query returned a model...')
    return model

def owl_str_to_model(owl_str):
    """Return a BioPAX model object from an OWL string.

    Parameters
    ----------
    owl_str : str
        The model as an OWL string.

    Returns
    -------
    biopax_model : org.biopax.paxtools.model.Model
        A BioPAX model object (java object).
    """
    io_class = autoclass('org.biopax.paxtools.io.SimpleIOHandler')
    io = io_class(autoclass('org.biopax.paxtools.model.BioPAXLevel').L3)
    bais = autoclass('java.io.ByteArrayInputStream')
    scs = autoclass('java.nio.charset.StandardCharsets')
    jstr = autoclass('java.lang.String')
    istream = bais(jstr(owl_str).getBytes(scs.UTF_8));
    biopax_model = io.convertFromOWL(istream)
    return biopax_model

def owl_to_model(fname):
    """Return a BioPAX model object from an OWL file.

    Parameters
    ----------
    fname : str
        The name of the OWL file containing the model.

    Returns
    -------
    biopax_model : org.biopax.paxtools.model.Model
        A BioPAX model object (java object).
    """
    io_class = autoclass('org.biopax.paxtools.io.SimpleIOHandler')
    io = io_class(autoclass('org.biopax.paxtools.model.BioPAXLevel').L3)

    try:
        file_is = autoclass('java.io.FileInputStream')(fname)
    except JavaException:
        logger.error('Could not open data file %s' % fname)
        return
    try:
        biopax_model = io.convertFromOWL(file_is)
    except JavaException as e:
        logger.error('Could not convert data file %s to BioPax model' % fname)
        logger.error(e)
        return

    file_is.close()

    return biopax_model

def model_to_owl(model, fname):
    """Save a BioPAX model object as an OWL file.

    Parameters
    ----------
    model : org.biopax.paxtools.model.Model
        A BioPAX model object (java object).
    fname : str
        The name of the OWL file to save the model in.
    """
    io_class = autoclass('org.biopax.paxtools.io.SimpleIOHandler')
    io = io_class(autoclass('org.biopax.paxtools.model.BioPAXLevel').L3)

    try:
        fileOS = autoclass('java.io.FileOutputStream')(fname)
    except JavaException:
        logger.error('Could not open data file %s' % fname)
        return
    l3_factory = autoclass('org.biopax.paxtools.model.BioPAXLevel').L3.getDefaultFactory()
    model_out = l3_factory.createModel()
    for r in model.getObjects().toArray():
        model_out.add(r)
    io.convertToOWL(model_out, fileOS)

    fileOS.close()

@@ -112,16 +112,32 @@
 logging%0A
+import requests%0A
 from ind
@@ -184,257 +184,8 @@
 on%0A%0A
-try:%0A    # Python 3%0A    from urllib.request import urlopen%0A    from urllib.error import HTTPError%0A    from urllib.parse import urlencode%0Aexcept ImportError:%0A    # Python 2%0A    from urllib2 import urlopen, HTTPError%0A    from urllib import urlencode%0A%0A
 logg
@@ -2068,119 +2068,94 @@
     
-try:%0A        res = urlopen(pc2_url + 'graph', data=urlencode(params).encode('utf-8'))%0A    except HTTPError as e
+res = requests.get(pc2_url + 'graph', params=params)%0A    if not res.status_code == 200
 :%0A  
@@ -2193,16 +2193,17 @@
  HTTP er
+r
 or code 
@@ -2209,18 +2209,27 @@
  %25d.' %25 
-e.
+res.status_
 code)%0A  
@@ -2246,17 +2246,16 @@
 rn None%0A
-%0A
     # We
@@ -2341,33 +2341,8 @@
 eam%0A
-    owl_str = res.read()%0A
     
@@ -2366,23 +2366,27 @@
 o_model(
-owl_str
+res.content
 )%0A    if

Switch pc client to use requests