from pydevd_constants import DictContains
import sys
import pydevd_vars
from os.path import basename
import traceback
try:
    from urllib import quote, quote_plus, unquote, unquote_plus
except:
    from urllib.parse import quote, quote_plus, unquote, unquote_plus  #@Reimport @UnresolvedImport

#===================================================================================================
# print_var_node
#===================================================================================================
def print_var_node(xml_node, stream):
    name = xml_node.getAttribute('name')
    value = xml_node.getAttribute('value')
    val_type = xml_node.getAttribute('type')

    found_as = xml_node.getAttribute('found_as')
    stream.write('Name: ')
    stream.write(unquote_plus(name))
    stream.write(', Value: ')
    stream.write(unquote_plus(value))
    stream.write(', Type: ')
    stream.write(unquote_plus(val_type))
    if found_as:
        stream.write(', Found as: %s' % (unquote_plus(found_as),))
    stream.write('\n')

#===================================================================================================
# print_referrers
#===================================================================================================
def print_referrers(obj, stream=None):
    if stream is None:
        stream = sys.stdout
    result = get_referrer_info(obj)
    from xml.dom.minidom import parseString
    dom = parseString(result)

    xml = dom.getElementsByTagName('xml')[0]
    for node in xml.childNodes:
        if node.nodeType == node.TEXT_NODE:
            continue

        if node.localName == 'for':
            stream.write('Searching references for: ')
            for child in node.childNodes:
                if child.nodeType == node.TEXT_NODE:
                    continue
                print_var_node(child, stream)

        elif node.localName == 'var':
            stream.write('Referrer found: ')
            print_var_node(node, stream)

        else:
            sys.stderr.write('Unhandled node: %s\n' % (node,))

    return result


#===================================================================================================
# get_referrer_info
#===================================================================================================
def get_referrer_info(searched_obj):
    DEBUG = 0
    if DEBUG:
        sys.stderr.write('Getting referrers info.\n')
    try:
        try:
            if searched_obj is None:
                ret = ['<xml>\n']

                ret.append('<for>\n')
                ret.append(pydevd_vars.varToXML(
                    searched_obj,
                    'Skipping getting referrers for None',
                    additionalInXml=' id="%s"' % (id(searched_obj),)))
                ret.append('</for>\n')
                ret.append('</xml>')
                ret = ''.join(ret)
                return ret

            obj_id = id(searched_obj)

            try:
                if DEBUG:
                    sys.stderr.write('Getting referrers...\n')
                import gc
                referrers = gc.get_referrers(searched_obj)
            except:
                traceback.print_exc()
                ret = ['<xml>\n']

                ret.append('<for>\n')
                ret.append(pydevd_vars.varToXML(
                    searched_obj,
                    'Exception raised while trying to get_referrers.',
                    additionalInXml=' id="%s"' % (id(searched_obj),)))
                ret.append('</for>\n')
                ret.append('</xml>')
                ret = ''.join(ret)
                return ret

            if DEBUG:
                sys.stderr.write('Found %s referrers.\n' % (len(referrers),))

            curr_frame = sys._getframe()
            frame_type = type(curr_frame)

            #Ignore this frame and any caller frame of this frame

            ignore_frames = {}  #Should be a set, but it's not available on all python versions.
            while curr_frame is not None:
                if basename(curr_frame.f_code.co_filename).startswith('pydev'):
                    ignore_frames[curr_frame] = 1
                curr_frame = curr_frame.f_back


            ret = ['<xml>\n']

            ret.append('<for>\n')
            if DEBUG:
                sys.stderr.write('Searching Referrers of obj with id="%s"\n' % (obj_id,))

            ret.append(pydevd_vars.varToXML(
                searched_obj,
                'Referrers of obj with id="%s"' % (obj_id,)))
            ret.append('</for>\n')

            all_objects = None

            for r in referrers:
                try:
                    if DictContains(ignore_frames, r):
                        continue  #Skip the references we may add ourselves
                except:
                    pass  #Ok: unhashable type checked...

                if r is referrers:
                    continue

                r_type = type(r)
                r_id = str(id(r))

                representation = str(r_type)

                found_as = ''
                if r_type == frame_type:
                    if DEBUG:
                        sys.stderr.write('Found frame referrer: %r\n' % (r,))
                    for key, val in r.f_locals.items():
                        if val is searched_obj:
                            found_as = key
                            break

                elif r_type == dict:
                    if DEBUG:
                        sys.stderr.write('Found dict referrer: %r\n' % (r,))

                    # Try to check if it's a value in the dict (and under which key it was found)
                    for key, val in r.items():
                        if val is searched_obj:
                            found_as = key
                            if DEBUG:
                                sys.stderr.write('    Found as %r in dict\n' % (found_as,))
                            break

                    #Ok, there's one annoying thing: many times we find it in a dict from an instance,
                    #but with this we don't directly have the class, only the dict, so, to workaround that
                    #we iterate over all reachable objects ad check if one of those has the given dict.
                    if all_objects is None:
                        all_objects = gc.get_objects()

                    for x in all_objects:
                        try:
                            if getattr(x, '__dict__', None) is r:
                                r = x
                                r_type = type(x)
                                r_id = str(id(r))
                                representation = str(r_type)
                                break
                        except:
                            pass  #Just ignore any error here (i.e.: ReferenceError, etc.)

                elif r_type in (tuple, list):
                    if DEBUG:
                        sys.stderr.write('Found tuple referrer: %r\n' % (r,))

                    #Don't use enumerate() because not all Python versions have it.
                    i = 0
                    for x in r:
                        if x is searched_obj:
                            found_as = '%s[%s]' % (r_type.__name__, i)
                            if DEBUG:
                                sys.stderr.write('    Found as %s in tuple: \n' % (found_as,))
                            break
                        i += 1

                if found_as:
                    found_as = ' found_as="%s"' % (pydevd_vars.makeValidXmlValue(found_as),)

                ret.append(pydevd_vars.varToXML(
                    r,
                    representation,
                    additionalInXml=' id="%s"%s' % (r_id, found_as)))
        finally:
            if DEBUG:
                sys.stderr.write('Done searching for references.\n')

            #If we have any exceptions, don't keep dangling references from this frame to any of our objects.
            all_objects = None
            referrers = None
            searched_obj = None
            r = None
            x = None
            key = None
            val = None
            curr_frame = None
            ignore_frames = None
    except:
        traceback.print_exc()
        ret = ['<xml>\n']

        ret.append('<for>\n')
        ret.append(pydevd_vars.varToXML(
            searched_obj,
            'Error getting referrers for:',
            additionalInXml=' id="%s"' % (id(searched_obj),)))
        ret.append('</for>\n')
        ret.append('</xml>')
        ret = ''.join(ret)
        return ret

    ret.append('</xml>')
    ret = ''.join(ret)
    return ret

