# This file is part of Androguard.
#
# Copyright (C) 2013, Anthony Desnos <desnos at t0t0.fr>
# All rights reserved.
#
# Androguard is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Androguard is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Androguard.  If not, see <http://www.gnu.org/licenses/>.


import sublime
import sublime_plugin

import os
import threading
import hashlib


from androguard.core.bytecodes import apk, dvm
from androguard.core.analysis import analysis
from androguard.core.analysis import ganalysis
from androguard.decompiler import decompiler
from androguard.core import androconf
from androguard.util import read

AG_DEX_VIEW = {}
AG_APK_VIEW = {}

AG_DEX_VIEW_LINK = {}
AG_REVERT_METHODS = {}
AG_REVERT_FIELDS = {}
AG_SC = {}
AG_METHOD_ID = {}
AG_FIELD_ID = {}
AG_CLASS_ID = {}
AG_AXML_ID = {}
AG_ARSC_ID = {}


AG_METHODS_LINE = {}
AG_FIELDS_LINE = {}
AG_CLASSES_LINE = {}

FILENAMES = {}


def get_setting(key, default=None):
    return sublime.load_settings("ag.sublime-settings").get(key, default)


def is_setting(key):
    return sublime.load_settings("ag.sublime-settings").has(key)


def get_bytecodes_class(dex_object, ana_object, class_obj):
    i_buffer = ""

    for i in class_obj.get_methods():
        i_buffer += dvm.get_bytecodes_method(dex_object, ana_object, i)

    return i_buffer


def get_field_info(field):
    i_buffer = ""

    i_buffer += "# %s->%s %s [access_flags=%s]\n#\n" % (field.get_class_name(), field.get_name(), field.get_descriptor(), field.get_access_flags_string())

    init_value = field.get_init_value()
    if init_value != None:
        i_buffer += repr(str(init_value.get_value()))

    return i_buffer


def get_axml_info(apk_object):
    i_buffer = "PERMISSIONS:\n"
    details_permissions = apk_object.get_details_permissions()
    for i in details_permissions:
        i_buffer += "\t%s %s\n" % (i, details_permissions[i])
    i_buffer += "\nMAIN ACTIVITY: %s\n" % apk_object.get_main_activity()

    i_buffer += "\nACTIVITIES:\n"
    for i in apk_object.get_activities():
        i_buffer += "\t%s\n" % (i)

    i_buffer += "\nSERVICES:\n"
    for i in apk_object.get_services():
        i_buffer += "\t%s\n" % (i)

    i_buffer += "\nRECEIVERS:\n"
    for i in apk_object.get_receivers():
        i_buffer += "\t%s\n" % (i)

    i_buffer += "\nPROVIDERS:\n"
    for i in apk_object.get_providers():
        i_buffer += "\t%s\n" % (i)

    return i_buffer


def get_sourcecode_method(dex_object, ana_object, method):
    return method.get_source()


class MethodView(object):
    def __init__(self, orig_id, method):
        self.view = sublime.active_window().new_file()
        self.dex_object, self.ana_object = AG_DEX_VIEW[orig_id]
        AG_DEX_VIEW_LINK[self.view.id()] = orig_id
        AG_REVERT_METHODS[method] = self.view

        self.view.set_name("%s-%s-%s.mag" % (method.get_class_name(), method.get_name(), method.get_descriptor()))
        self.view.set_syntax_file("Packages/ag-st/agbytecodes.tmLanguage")

        self.view.set_scratch(True)
        edit = self.view.begin_edit()

        i_buffer = dvm.get_bytecodes_method(self.dex_object, self.ana_object, method)
        AG_METHOD_ID[self.view.id()] = method

        self.view.replace(edit, sublime.Region(0, self.view.size()), i_buffer)
        self.view.end_edit(edit)
        self.view.sel().clear()

        if self.view.id() not in AG_SC:
            AG_SC[self.view.id()] = False


class FieldView(object):
    def __init__(self, orig_id, field):
        self.view = sublime.active_window().new_file()
        self.dex_object, self.ana_object = AG_DEX_VIEW[orig_id]
        AG_DEX_VIEW_LINK[self.view.id()] = orig_id
        AG_REVERT_FIELDS[field] = self.view

        self.view.set_name("%s-%s-%s.fag" % (field.get_class_name(), field.get_name(), field.get_descriptor()))
        self.view.set_syntax_file("Packages/ag-st/agbytecodes.tmLanguage")

        self.view.set_scratch(True)
        edit = self.view.begin_edit()

        i_buffer = get_field_info(field)
        AG_FIELD_ID[self.view.id()] = field

        self.view.replace(edit, sublime.Region(0, self.view.size()), i_buffer)
        self.view.end_edit(edit)
        self.view.sel().clear()


class ClassView(object):
    def __init__(self, orig_id, class_obj):
        self.view = sublime.active_window().new_file()
        self.dex_object, self.ana_object = AG_DEX_VIEW[orig_id]
        AG_DEX_VIEW_LINK[self.view.id()] = orig_id

        self.view.set_name("%s.cag" % (class_obj.get_name()))
        self.view.set_syntax_file("Packages/ag-st/agbytecodes.tmLanguage")

        self.view.set_scratch(True)
        edit = self.view.begin_edit()

        i_buffer = get_bytecodes_class(self.dex_object, self.ana_object, class_obj)

        AG_CLASS_ID[self.view.id()] = class_obj

        self.view.replace(edit, sublime.Region(0, self.view.size()), i_buffer)
        self.view.end_edit(edit)
        self.view.sel().clear()

        if self.view.id() not in AG_SC:
            AG_SC[self.view.id()] = False


class AgDoubleClick(sublime_plugin.TextCommand):
    def extract_bb(self, raw, position):
        raw_list = raw.split(" ")
        idx = 0
        for i in raw_list:
            begin = idx
            end = idx + len(i)

            if position >= begin and position <= end:
                if ":" in i:
                    return i.split(":")[-1]
                return i
            idx += len(i)
        return None

    def run(self, edit):
        if self.view.id() in AG_METHOD_ID and self.view.id() in AG_SC:
            if not AG_SC[self.view.id()]:
                for sel in self.view.sel():
                    if self.view.scope_name(sel.begin()) == 'source.agbt markup.list ':
                        scope_region = self.view.extract_scope(sel.begin())

                        scope_value = self.view.substr(scope_region)

                        bb_selected = self.extract_bb(scope_value, sel.begin() - scope_region.begin())
                        region_bb = self.view.find("^(%s)" % bb_selected, 0)
                        self.view.run_command("goto_line", {"line": self.view.rowcol(region_bb.end())[0] + 1})

        if self.view.id() in AG_DEX_VIEW:
            current_view_id = self.view.id()
            datas = []
            try:
                for sel in self.view.sel():
                    x, y = self.view.rowcol(sel.begin())
                    datas.append(x)
            except AttributeError:
                pass

            dex_object, ana_object = AG_DEX_VIEW[self.view.id()]

            for x in datas:
                if x in AG_METHODS_LINE[current_view_id]:
                    MethodView(self.view.id(), AG_METHODS_LINE[current_view_id][x])
                elif x in AG_FIELDS_LINE[current_view_id]:
                    FieldView(self.view.id(), AG_FIELDS_LINE[current_view_id][x])
                elif x in AG_CLASSES_LINE[current_view_id]:
                    ClassView(self.view.id(), AG_CLASSES_LINE[current_view_id][x])

        elif self.view.id() in AG_APK_VIEW:
            apk_object = AG_APK_VIEW[self.view.id()]

            datas = []
            try:
                for sel in self.view.sel():
                    datas.append(self.view.substr(self.view.line(sel)))
            except AttributeError:
                pass

            filename = FILENAMES[self.view.id()]
            for x in datas:
                if x == "classes.dex":
                    at = AnalyseDexThread(sublime.active_window().new_file(), filename + "-classes", apk_object.get_dex())
                    at.run()
                elif x == "AndroidManifest.xml":
                    at = AnalyseAXMLThread(sublime.active_window().new_file(), filename + "-AndroidManifest", apk_object)
                    at.run()
                elif x == "resources.arsc":
                    at = AnalyseARSCThread(sublime.active_window().new_file(), filename + "-resources", apk_object.get_file(x))
                    at.run()
                elif ".xml" in x:
                    at = AnalyseAXMLSimpleThread(sublime.active_window().new_file(), filename + "-%s" + x, apk_object.get_file(x))
                    at.run()
                else:
                    new_view = sublime.active_window().new_file()
                    new_view.set_name("%s-%s" % (filename, x))
                    new_view.set_syntax_file("Packages/Text/Plain text.tmLanguage")

                    new_view.set_scratch(True)
                    edit = new_view.begin_edit()
                    new_view.sel().clear()

                    i_buffer = apk_object.get_file(x).decode('utf-8', 'replace')

                    new_view.replace(edit, sublime.Region(0, new_view.size()), i_buffer)
                    new_view.end_edit(edit)
                    new_view.set_read_only(True)


class ThreadProgress(object):
    def __init__(self, thread, message, success_message):
        self.thread = thread
        self.message = message
        self.success_message = success_message
        self.addend = 1
        self.size = 8
        sublime.set_timeout(lambda: self.run(0), 100)

    def run(self, i):
        if not self.thread.is_alive():
            if hasattr(self.thread, 'result') and not self.thread.result:
                sublime.status_message('')
                return
            sublime.status_message(self.success_message)
            return

        before = i % self.size
        after = (self.size - 1) - before
        sublime.status_message('%s [%s=%s]' % \
            (self.message, ' ' * before, ' ' * after))
        if not after:
            self.addend = -1
        if not before:
            self.addend = 1
        i += self.addend
        sublime.set_timeout(lambda: self.run(i), 100)


class AnalyseAXMLThread(object):
    def __init__(self, view, filename, apk_object):
        self.view = view
        self.apk_object = apk_object
        self.filename = filename
        #threading.Thread.__init__(self)

    def run(self):
        self.view.set_name("%s.uaxml" % (self.filename))

        self.view.set_scratch(True)
        edit = self.view.begin_edit()
        self.view.sel().clear()
        #self.view.set_syntax_file("Packages/ag-st/agapk.tmLanguage")

        i_buffer = get_axml_info(self.apk_object)

        self.view.replace(edit, sublime.Region(0, self.view.size()), i_buffer)
        self.view.end_edit(edit)
        self.view.set_read_only(True)

        AG_AXML_ID[self.view.id()] = self.apk_object

        if self.view.id() not in AG_SC:
            AG_SC[self.view.id()] = False


class AnalyseAXMLSimpleThread(object):
    def __init__(self, view, filename, raw_object):
        self.view = view
        self.raw_object = raw_object
        self.filename = filename
        #threading.Thread.__init__(self)

    def run(self):
        self.view.set_name("%s.uaxml" % (self.filename))

        self.view.set_scratch(True)
        edit = self.view.begin_edit()
        self.view.sel().clear()
        self.view.set_syntax_file("Packages/XML/XML.tmLanguage")

        ap = apk.AXMLPrinter(self.raw_object)
        i_buffer = ap.get_xml()

        self.view.replace(edit, sublime.Region(0, self.view.size()), i_buffer)
        self.view.end_edit(edit)
        self.view.set_read_only(True)


class AnalyseARSCThread(object):
    def __init__(self, view, filename, raw_object):
        self.view = view
        self.raw_object = raw_object
        self.filename = filename
        #threading.Thread.__init__(self)

    def run(self):
        self.view.set_name("%s.uarsc" % (self.filename))

        self.view.set_scratch(True)
        edit = self.view.begin_edit()
        self.view.sel().clear()
        #self.view.set_syntax_file("Packages/ag-st/agapk.tmLanguage")

        arscobj = apk.ARSCParser(self.raw_object)
        i_buffer = apk.get_arsc_info(arscobj)

        self.view.replace(edit, sublime.Region(0, self.view.size()), i_buffer)
        self.view.end_edit(edit)
        self.view.set_read_only(True)

        AG_ARSC_ID[self.view.id()] = arscobj

        if self.view.id() not in AG_SC:
            AG_SC[self.view.id()] = False


class AnalyseAPKThread(object):
    def __init__(self, view, filename, raw):
        self.view = view
        self.raw = raw
        self.filename = filename
        #threading.Thread.__init__(self)

    def run(self):
        apk_object = apk.APK(self.raw, raw=True)
        self.view.set_name("%s.uapk" % (self.filename))

        self.view.set_scratch(True)
        edit = self.view.begin_edit()
        self.view.sel().clear()
        self.view.set_syntax_file("Packages/ag-st/agapk.tmLanguage")

        i_buffer = ""
#        files_list = apk_object.get_files_types()
#        for i in files_list:
#            i_buffer += "%s: %s" % (i, files_list[i])

        for i in sorted(apk_object.get_files()):
            i_buffer += "%s\n" % i

        self.view.replace(edit, sublime.Region(0, self.view.size()), i_buffer)
        self.view.end_edit(edit)
        self.view.set_read_only(True)
        AG_APK_VIEW[self.view.id()] = apk_object
        FILENAMES[self.view.id()] = hashlib.sha1(apk_object.get_raw()).hexdigest()


class AnalyseDexThread(object):  # (threading.Thread):
    def __init__(self, view, filename, raw):
        self.view = view
        self.raw = raw
        self.filename = filename
        #threading.Thread.__init__(self)

    def run(self):
        if androconf.is_android_raw(self.raw) == "DEY":
            dex_object = dvm.DalvikOdexVMFormat(self.raw)
        else:
            dex_object = dvm.DalvikVMFormat(self.raw)

        ana_object = analysis.uVMAnalysis(dex_object)
        gvm_object = ganalysis.GVMAnalysis(ana_object, None)

        dex_object.set_vmanalysis(ana_object)
        dex_object.set_gvmanalysis(gvm_object)

        for i in androconf.CONF:
            if is_setting(i):
                androconf.CONF[i] = get_setting(i)

        decompiler_option = get_setting("DEFAULT_DECOMPILER", "dad")

        if decompiler_option == "dex2jad":
            dex_object.set_decompiler(decompiler.DecompilerDex2Jad(
                dex_object,
                androconf.CONF["PATH_DEX2JAR"],
                androconf.CONF["BIN_DEX2JAR"],
                androconf.CONF["PATH_JAD"],
                androconf.CONF["BIN_JAD"],
                androconf.CONF["TMP_DIRECTORY"]))
        elif decompiler_option == "ded":
            dex_object.set_decompiler(decompiler.DecompilerDed(
                dex_object,
                androconf.CONF["PATH_DED"],
                androconf.CONF["BIN_DED"],
                androconf.CONF["TMP_DIRECTORY"]))
        else:
            dex_object.set_decompiler(decompiler.DecompilerDAD(dex_object, ana_object))

        dex_object.create_xref()
        dex_object.create_dref()

        self.view.set_name("%s.ag" % (self.filename))

        self.view.set_scratch(True)
        edit = self.view.begin_edit()
        self.view.sel().clear()
        self.view.set_syntax_file("Packages/ag-st/ag.tmLanguage")

        by_package = {}
        for current_class in dex_object.get_classes():
          name = current_class.get_name()

          try:
            by_package[os.path.dirname(name)].append(current_class)
          except KeyError:
            by_package[os.path.dirname(name)] = []
            by_package[os.path.dirname(name)].append(current_class)

        b_buffer = ""
        line = 0

        AG_METHODS_LINE[self.view.id()] = {}
        AG_CLASSES_LINE[self.view.id()] = {}
        AG_FIELDS_LINE[self.view.id()] = {}
        for key in sorted(by_package.iterkeys()):
            b_buffer += "%s\n" % key
            line += 1

            for c_class in sorted(by_package[key], key=lambda k: k.get_name()):
                b_buffer += "\t%s extends %s\n" % (c_class.get_name()[1:-1], c_class.get_superclassname()[1:-1])
                AG_CLASSES_LINE[self.view.id()][line] = c_class
                line += 1

                for j in c_class.get_methods():
                    b_buffer += "\t\tmethod: %s %s [%s] size:%d\n" % (j.get_name(), j.get_descriptor(), j.get_access_flags_string(), j.get_length())
                    AG_METHODS_LINE[self.view.id()][line] = j
                    line += 1

                b_buffer += "\n"
                line += 1

                for j in c_class.get_fields():
                    b_buffer += "\t\tfield: %s %s [%s %s]" % (j.get_name(), j.get_descriptor(), j.get_access_flags_string(), dvm.get_type(j.get_descriptor()))

                    init_value = j.get_init_value()
                    if init_value != None:
                        b_buffer += " (%s)" % repr(str(init_value.get_value()))
                    b_buffer += "\n"

                    AG_FIELDS_LINE[self.view.id()][line] = j
                    line += 1

                b_buffer += "\n"
                line += 1

        l = dex_object.print_classes_hierarchy()
        h_buffer = ""
        for i in l:
            h_buffer += i + "\n"

        b_buffer += h_buffer

        self.view.replace(edit, sublime.Region(0, self.view.size()), b_buffer)
        self.view.end_edit(edit)
        self.view.set_read_only(True)
        AG_DEX_VIEW[self.view.id()] = (dex_object, ana_object)
        FILENAMES[self.view.id()] = hashlib.sha1(dex_object.get_buff()).hexdigest()


class AgCommand(sublime_plugin.WindowCommand):
  def run(self):
    self.view = self.window.active_view()

    filename = self.view.file_name()

    ret = androconf.is_android(filename)
    if ret == "APK":
        at = AnalyseAPKThread(self.window.new_file(), filename, read(filename))
        at.run()
    elif ret == "DEX" or ret == "DEY":
        at = AnalyseDexThread(self.window.new_file(), filename, read(filename))
        at.run()
    elif ret == "AXML":
        at = AnalyseAXMLSimpleThread(self.window.new_file(), filename, read(filename))
        at.run()
    elif ret == "ARSC":
        at = AnalyseARSCThread(self.window.new_file(), filename, read(filename))
        at.run()

    #thread = AnalyseThread(self.window.new_file(), filename, read(filename))
    #thread.start()
    #ThreadProgress(thread,
    #               "Analysing app ...",
    #               "Finished !")


def get_strings_info(dex_object, ana_object):
    i_buffer = ""

    for i in dex_object.get_strings():
        i_buffer += repr(i) + "\n"
        if ana_object != None:
            ref = ana_object.tainted_variables.get_string(i)
            if ref != None:
                for path in ref.get_paths():
                    access, idx = path[0]
                    m_idx = path[1]
                    method = dex_object.get_cm_method(m_idx)
                    i_buffer += "\t\t%s %x %s->%s %s\n" % (access, idx, method[0], method[1], method[2][0] + method[2][1])

    return i_buffer


class AgStrings(sublime_plugin.WindowCommand):
  def run(self):
    self.view = self.window.active_view()
    if self.view.id() in AG_DEX_VIEW:
        dex_object, ana_object = AG_DEX_VIEW[self.view.id()]

        view = sublime.active_window().new_file()

        filename = FILENAMES[self.view.id()]
        view.set_name("%s.strings" % filename)

        view.set_scratch(True)
        edit = view.begin_edit()

        i_buffer = get_strings_info(dex_object, ana_object)

        view.replace(edit, sublime.Region(0, view.size()), i_buffer)
        view.end_edit(edit)
        view.sel().clear()


class AgTrCommand(sublime_plugin.WindowCommand):
    def run(self):
        self.view = self.window.active_view()

        if self.view.id() in AG_METHOD_ID:
            dex_object, ana_object = AG_DEX_VIEW[AG_DEX_VIEW_LINK[self.view.id()]]

            self.view.sel().clear()
            if not AG_SC[self.view.id()]:
                self.view.set_syntax_file("Packages/Java/Java.tmLanguage")
                i_buffer = get_sourcecode_method(dex_object, ana_object, AG_METHOD_ID[self.view.id()])
            else:
                self.view.set_syntax_file("Packages/ag-st/agbytecodes.tmLanguage")
                i_buffer = dvm.get_bytecodes_method(dex_object, ana_object, AG_METHOD_ID[self.view.id()])

            self.view.set_read_only(False)
            edit = self.view.begin_edit()
            self.view.replace(edit, sublime.Region(0, self.view.size()), i_buffer)
            self.view.end_edit(edit)
            AG_SC[self.view.id()] = not AG_SC[self.view.id()]

        elif self.view.id() in AG_CLASS_ID:
            dex_object, ana_object = AG_DEX_VIEW[AG_DEX_VIEW_LINK[self.view.id()]]

            self.view.sel().clear()

            if not AG_SC[self.view.id()]:
                self.view.set_syntax_file("Packages/Java/Java.tmLanguage")
                i_buffer = AG_CLASS_ID[self.view.id()].get_source()
            else:
                self.view.set_syntax_file("Packages/ag-st/agbytecodes.tmLanguage")
                i_buffer = get_bytecodes_class(dex_object, ana_object, AG_CLASS_ID[self.view.id()])

            self.view.set_read_only(False)
            edit = self.view.begin_edit()
            self.view.replace(edit, sublime.Region(0, self.view.size()), i_buffer)
            self.view.end_edit(edit)

            AG_SC[self.view.id()] = not AG_SC[self.view.id()]

        elif self.view.id() in AG_AXML_ID:
            apk_object = AG_AXML_ID[self.view.id()]

            self.view.sel().clear()

            if not AG_SC[self.view.id()]:
                i_buffer = apk_object.get_android_manifest_xml().toprettyxml()
                self.view.set_syntax_file("Packages/XML/XML.tmLanguage")
            else:
                i_buffer = get_axml_info(apk_object)

            self.view.set_read_only(False)
            edit = self.view.begin_edit()
            self.view.replace(edit, sublime.Region(0, self.view.size()), i_buffer)
            self.view.end_edit(edit)

            AG_SC[self.view.id()] = not AG_SC[self.view.id()]


class AgRefFromCommand(sublime_plugin.WindowCommand):
    def set_ref(self, value):
        if value == -1:
            return

        if self.view.id() in AG_METHOD_ID:
            self.set_ref_method(value, 0)
        elif self.view.id() in AG_FIELD_ID:
            self.set_ref_method(value, 1)

    def set_ref_method(self, value, action):
        if action == 0:
            method = AG_METHOD_ID[self.view.id()]
            x_method = method.XREFfrom.items[value][0]
        else:
            field = AG_FIELD_ID[self.view.id()]
            x_method = field.DREFr.items[value][0]

        if x_method in AG_REVERT_METHODS:
            if self.window.get_view_index(AG_REVERT_METHODS[x_method])[0] != -1:
                self.window.focus_view(AG_REVERT_METHODS[x_method])
            else:
                del AG_REVERT_METHODS[x_method]
                MethodView(AG_DEX_VIEW_LINK[self.view.id()], x_method)
        else:
            MethodView(AG_DEX_VIEW_LINK[self.view.id()], x_method)

    def run(self):
        self.option_list = []

        self.view = self.window.active_view()
        if self.view.id() in AG_METHOD_ID:
            method = AG_METHOD_ID[self.view.id()]
            for i in method.XREFfrom.items:
                x_method = i[0]
                self.option_list.append("%s %s %s" % (x_method.get_class_name(), x_method.get_name(), x_method.get_descriptor()))
        elif self.view.id() in AG_FIELD_ID:
            field = AG_FIELD_ID[self.view.id()]
            for i in field.DREFr.items:
                x_method = i[0]
                self.option_list.append("%s %s %s" % (x_method.get_class_name(), x_method.get_name(), x_method.get_descriptor()))

        self.window.show_quick_panel(self.option_list, self.set_ref)


class AgRefToCommand(sublime_plugin.WindowCommand):
    def set_ref(self, value):
        if value == -1:
            return

        if self.view.id() in AG_METHOD_ID:
            self.set_ref_method(value, 0)
        elif self.view.id() in AG_FIELD_ID:
            self.set_ref_method(value, 1)

    def set_ref_method(self, value, action):
        if action == 0:
            method = AG_METHOD_ID[self.view.id()]
            x_method = method.XREFto.items[value][0]
        else:
            field = AG_FIELD_ID[self.view.id()]
            x_method = field.DREFw.items[value][0]

        if x_method in AG_REVERT_METHODS:
                if self.window.get_view_index(AG_REVERT_METHODS[x_method])[0] != -1:
                    self.window.focus_view(AG_REVERT_METHODS[x_method])
                else:
                    del AG_REVERT_METHODS[x_method]
                    MethodView(AG_DEX_VIEW_LINK[self.view.id()], x_method)
        else:
            MethodView(AG_DEX_VIEW_LINK[self.view.id()], x_method)

    def run(self):
        self.option_list = []

        self.view = self.window.active_view()
        if self.view.id() in AG_METHOD_ID:
            method = AG_METHOD_ID[self.view.id()]
            for i in method.XREFto.items:
                x_method = i[0]
                self.option_list.append("%s %s %s" % (x_method.get_class_name(), x_method.get_name(), x_method.get_descriptor()))
        elif self.view.id() in AG_FIELD_ID:
            field = AG_FIELD_ID[self.view.id()]
            for i in field.DREFw.items:
                x_method = i[0]
                self.option_list.append("%s %s %s" % (x_method.get_class_name(), x_method.get_name(), x_method.get_descriptor()))

        self.window.show_quick_panel(self.option_list, self.set_ref)


class AgReset(sublime_plugin.WindowCommand):
  def run(self):
    self.view = self.window.active_view()

    global AG_DEX_VIEW
    global AG_APK_VIEW
    global AG_DEX_VIEW_LINK
    global AG_REVERT_METHODS
    global AG_REVERT_FIELDS
    global AG_SC
    global AG_METHOD_ID
    global AG_FIELD_ID
    global AG_CLASS_ID
    global AG_METHODS_LINE
    global AG_FIELDS_LINE
    global AG_CLASSES_LINE
    global AG_AXML_ID
    global AG_ARSC_ID

    AG_DEX_VIEW = {}
    AG_APK_VIEW = {}

    AG_DEX_VIEW_LINK = {}
    AG_REVERT_METHODS = {}
    AG_REVERT_FIELDS = {}
    AG_SC = {}
    AG_METHOD_ID = {}
    AG_FIELD_ID = {}
    AG_CLASS_ID = {}
    AG_AXML_ID = {}
    AG_ARSC_ID = {}

    AG_METHODS_LINE = {}
    AG_FIELDS_LINE = {}
    AG_CLASSES_LINE = {}

    print "Reset Androguard Plugin"
