"""
LLDB AppKit formatters

part of The LLVM Compiler Infrastructure
This file is distributed under the University of Illinois Open Source
License. See LICENSE.TXT for details.
"""
# example summary provider for NSBundle
# the real summary is now C++ code built into LLDB
import lldb
import ctypes
import lldb.runtime.objc.objc_runtime
import lldb.formatters.metrics
import NSURL
import lldb.formatters.Logger

statistics = lldb.formatters.metrics.Metrics()
statistics.add_metric('invalid_isa')
statistics.add_metric('invalid_pointer')
statistics.add_metric('unknown_class')
statistics.add_metric('code_notrun')

# despite the similary to synthetic children providers, these classes are not
# trying to provide anything but a summary for an NSURL, so they need not
# obey the interface specification for synthetic children providers


class NSBundleKnown_SummaryProvider:

    def adjust_for_architecture(self):
        pass

    def __init__(self, valobj, params):
        logger = lldb.formatters.Logger.Logger()
        self.valobj = valobj
        self.sys_params = params
        if not(self.sys_params.types_cache.NSString):
            self.sys_params.types_cache.NSString = self.valobj.GetTarget(
            ).FindFirstType('NSString').GetPointerType()
        self.update()

    def update(self):
        logger = lldb.formatters.Logger.Logger()
        self.adjust_for_architecture()

    # we need to skip the ISA, plus four other values
    # that are luckily each a pointer in size
    # which makes our computation trivial :-)
    def offset(self):
        logger = lldb.formatters.Logger.Logger()
        return 5 * self.sys_params.pointer_size

    def url_text(self):
        logger = lldb.formatters.Logger.Logger()
        global statistics
        text = self.valobj.CreateChildAtOffset(
            "text", self.offset(), self.sys_params.types_cache.NSString)
        my_string = text.GetSummary()
        if (my_string is None) or (my_string == ''):
            statistics.metric_hit(
                'unknown_class', str(
                    self.valobj.GetName()) + " triggered unknown pointer location")
            return NSBundleUnknown_SummaryProvider(
                self.valobj, self.sys_params).url_text()
        else:
            statistics.metric_hit('code_notrun', self.valobj)
            return my_string


class NSBundleUnknown_SummaryProvider:

    def adjust_for_architecture(self):
        pass

    def __init__(self, valobj, params):
        logger = lldb.formatters.Logger.Logger()
        self.valobj = valobj
        self.sys_params = params
        self.update()

    def update(self):
        logger = lldb.formatters.Logger.Logger()
        self.adjust_for_architecture()

    def url_text(self):
        logger = lldb.formatters.Logger.Logger()
        stream = lldb.SBStream()
        self.valobj.GetExpressionPath(stream)
        expr = "(NSString*)[" + stream.GetData() + " bundlePath]"
        url_text_vo = self.valobj.CreateValueFromExpression("path", expr)
        if url_text_vo.IsValid():
            return url_text_vo.GetSummary()
        return '<variable is not NSBundle>'


def GetSummary_Impl(valobj):
    logger = lldb.formatters.Logger.Logger()
    global statistics
    class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
        valobj, statistics)
    if wrapper:
        return wrapper

    name_string = class_data.class_name()
    logger >> "class name is: " + str(name_string)

    if name_string == 'NSBundle':
        wrapper = NSBundleKnown_SummaryProvider(valobj, class_data.sys_params)
        # [NSBundle mainBundle] does return an object that is
        # not correctly filled out for our purposes, so we still
        # end up having to run code in that case
        # statistics.metric_hit('code_notrun',valobj)
    else:
        wrapper = NSBundleUnknown_SummaryProvider(
            valobj, class_data.sys_params)
        statistics.metric_hit(
            'unknown_class',
            valobj.GetName() +
            " seen as " +
            name_string)
    return wrapper


def NSBundle_SummaryProvider(valobj, dict):
    logger = lldb.formatters.Logger.Logger()
    provider = GetSummary_Impl(valobj)
    if provider is not None:
        if isinstance(
                provider,
                lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
            return provider.message()
        try:
            summary = provider.url_text()
        except:
            summary = None
        logger >> "got summary " + str(summary)
        if summary is None or summary == '':
            summary = '<variable is not NSBundle>'
        return summary
    return 'Summary Unavailable'


def __lldb_init_module(debugger, dict):
    debugger.HandleCommand(
        "type summary add -F NSBundle.NSBundle_SummaryProvider NSBundle")
