# -*- coding: utf-8 -*-
# vim: sw=4:ts=4:expandtab
"""
riko.bado.util
~~~~~~~~~~~~~~
Provides functions for creating asynchronous riko pipes

Examples:
    basic usage::

        >>> from riko import get_path
        >>> from riko.bado.util import xml2etree
"""
from __future__ import (
    absolute_import, division, print_function, unicode_literals)

from os import environ
from sys import executable
from functools import partial
from html.entities import entitydefs, name2codepoint

from builtins import *

from riko.lib.utils import _make_content

try:
    from twisted.internet.defer import maybeDeferred, Deferred
except ImportError:
    maybeDeferred = lambda *args: None
else:
    from twisted.internet import defer
    from twisted.internet.utils import getProcessOutput
    from twisted.internet.reactor import callLater

    from . import microdom
    from .microdom import EntityReference

    async_none = defer.succeed(None)
    async_return = partial(defer.succeed)
    async_partial = lambda f, **kwargs: partial(maybeDeferred, f, **kwargs)

DEF2NAME = {v: k for k, v in entitydefs.items()}


def async_sleep(seconds):
    d = Deferred()
    callLater(seconds, d.callback, None)
    return d


def defer_to_process(command):
    return getProcessOutput(executable, ['-c', command], environ)


def def2unicode(entitydef):
    """Convert an HTML entity reference into unicode.
    Double check if I need this since it seems to convert the input back into
    itself!
    """
    try:
        name = DEF2NAME[entitydef]
    except KeyError:
        cp = int(entitydef.lstrip('&#').rstrip(';'))
    else:
        cp = name2codepoint[name]

    return chr(cp)


def xml2etree(f, xml=True):
    readable = hasattr(f, 'read')

    if xml and readable:
        parse = microdom.parseXML
    elif readable:
        parse = partial(microdom.parse, lenient=True)
    elif xml:
        parse = microdom.parseXMLString
    else:
        parse = partial(microdom.parseString, lenient=True)

    return parse(f)


def etree2dict(element, tag='content'):
    """Convert a microdom element tree into a dict imitating how Yahoo Pipes
    does it.

    TODO: checkout twisted.words.xish
    """
    i = dict(element.attributes) if hasattr(element, 'attributes') else {}
    value = element.nodeValue if hasattr(element, 'nodeValue') else None

    if isinstance(element, EntityReference):
        value = def2unicode(value)

    i.update(_make_content(i, value, tag))

    for child in element.childNodes:
        tag = child.tagName if hasattr(child, 'tagName') else 'content'
        value = etree2dict(child, tag)

        # try to join the content first since microdom likes to split up
        # elements that contain a mix of text and entity reference
        try:
            i.update(_make_content(i, value, tag, append=False))
        except TypeError:
            i.update(_make_content(i, value, tag))

    if ('content' in i) and not set(i).difference(['content']):
        # element is leaf node and doesn't have attributes
        i = i['content']

    return i

@@ -455,20 +455,8 @@
 port
- entitydefs,
  nam
@@ -1044,57 +1044,8 @@
 s)%0A%0A
-DEF2NAME = %7Bv: k for k, v in entitydefs.items()%7D%0A
 %0A%0Ade
@@ -1332,193 +1332,47 @@
     
-Double check if I need this since it seems to convert the input back into%0A    itself!%0A    %22%22%22%0A    try:%0A        name = DEF2NAME%5Bentitydef%5D%0A    except KeyError:%0A        cp = int(entitydef
+%22%22%22%0A    cleaned = entitydef.lstrip('&')
 .lst
@@ -1376,17 +1376,16 @@
 lstrip('
-&
 #').rstr
@@ -1395,32 +1395,56 @@
 ';')
-)
 %0A    
-else:%0A        cp =
+cp = int(cleaned) if '&#' in entitydef else
  nam
@@ -1459,14 +1459,16 @@
 int%5B
-name%5D%0A
+cleaned%5D
 %0A   

Remove unnecessary entity conversion