"""
LLDB AppKit formatters

Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
See https://llvm.org/LICENSE.txt for license information.
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
"""
# example summary provider for NSArray
# 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 lldb.formatters.Logger

try:
    basestring
except NameError:
    basestring = str

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')

# much less functional than the other two cases below
# just runs code to get to the count and then returns
# no children


class NSArrayKVC_SynthProvider:

    def adjust_for_architecture(self):
        pass

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

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

    def num_children(self):
        logger = lldb.formatters.Logger.Logger()
        stream = lldb.SBStream()
        self.valobj.GetExpressionPath(stream)
        num_children_vo = self.valobj.CreateValueFromExpression(
            "count", "(int)[" + stream.GetData() + " count]")
        if num_children_vo.IsValid():
            return num_children_vo.GetValueAsUnsigned(0)
        return "<variable is not NSArray>"

# much less functional than the other two cases below
# just runs code to get to the count and then returns
# no children


class NSArrayCF_SynthProvider:

    def adjust_for_architecture(self):
        pass

    def __init__(self, valobj, dict, params):
        logger = lldb.formatters.Logger.Logger()
        self.valobj = valobj
        self.sys_params = params
        if not (self.sys_params.types_cache.ulong):
            self.sys_params.types_cache.ulong = self.valobj.GetType(
            ).GetBasicType(lldb.eBasicTypeUnsignedLong)
        self.update()

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

    def num_children(self):
        logger = lldb.formatters.Logger.Logger()
        num_children_vo = self.valobj.CreateChildAtOffset(
            "count", self.sys_params.cfruntime_size, self.sys_params.types_cache.ulong)
        return num_children_vo.GetValueAsUnsigned(0)


class NSArrayI_SynthProvider:

    def adjust_for_architecture(self):
        pass

    def __init__(self, valobj, dict, params):
        logger = lldb.formatters.Logger.Logger()
        self.valobj = valobj
        self.sys_params = params
        if not(self.sys_params.types_cache.long):
            self.sys_params.types_cache.long = self.valobj.GetType(
            ).GetBasicType(lldb.eBasicTypeLong)
        self.update()

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

    # skip the isa pointer and get at the size
    def num_children(self):
        logger = lldb.formatters.Logger.Logger()
        count = self.valobj.CreateChildAtOffset(
            "count",
            self.sys_params.pointer_size,
            self.sys_params.types_cache.long)
        return count.GetValueAsUnsigned(0)


class NSArrayM_SynthProvider:

    def adjust_for_architecture(self):
        pass

    def __init__(self, valobj, dict, params):
        logger = lldb.formatters.Logger.Logger()
        self.valobj = valobj
        self.sys_params = params
        if not(self.sys_params.types_cache.long):
            self.sys_params.types_cache.long = self.valobj.GetType(
            ).GetBasicType(lldb.eBasicTypeLong)
        self.update()

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

    # skip the isa pointer and get at the size
    def num_children(self):
        logger = lldb.formatters.Logger.Logger()
        count = self.valobj.CreateChildAtOffset(
            "count",
            self.sys_params.pointer_size,
            self.sys_params.types_cache.long)
        return count.GetValueAsUnsigned(0)

# this is the actual synth provider, but is just a wrapper that checks
# whether valobj is an instance of __NSArrayI or __NSArrayM and sets up an
# appropriate backend layer to do the computations


class NSArray_SynthProvider:

    def adjust_for_architecture(self):
        pass

    def __init__(self, valobj, dict):
        logger = lldb.formatters.Logger.Logger()
        self.valobj = valobj
        self.adjust_for_architecture()
        self.error = False
        self.wrapper = self.make_wrapper()
        self.invalid = (self.wrapper is None)

    def num_children(self):
        logger = lldb.formatters.Logger.Logger()
        if self.wrapper is None:
            return 0
        return self.wrapper.num_children()

    def update(self):
        logger = lldb.formatters.Logger.Logger()
        if self.wrapper is None:
            return
        self.wrapper.update()

    # this code acts as our defense against NULL and uninitialized
    # NSArray pointers, which makes it much longer than it would be otherwise
    def make_wrapper(self):
        logger = lldb.formatters.Logger.Logger()
        if self.valobj.GetValueAsUnsigned() == 0:
            self.error = True
            return lldb.runtime.objc.objc_runtime.InvalidPointer_Description(
                True)
        else:
            global statistics
            class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
                self.valobj, statistics)
            if wrapper:
                self.error = True
                return wrapper

        name_string = class_data.class_name()

        logger >> "Class name is " + str(name_string)

        if name_string == '__NSArrayI':
            wrapper = NSArrayI_SynthProvider(
                self.valobj, dict, class_data.sys_params)
            statistics.metric_hit('code_notrun', self.valobj.GetName())
        elif name_string == '__NSArrayM':
            wrapper = NSArrayM_SynthProvider(
                self.valobj, dict, class_data.sys_params)
            statistics.metric_hit('code_notrun', self.valobj.GetName())
        elif name_string == '__NSCFArray':
            wrapper = NSArrayCF_SynthProvider(
                self.valobj, dict, class_data.sys_params)
            statistics.metric_hit('code_notrun', self.valobj.GetName())
        else:
            wrapper = NSArrayKVC_SynthProvider(
                self.valobj, dict, class_data.sys_params)
            statistics.metric_hit(
                'unknown_class', str(
                    self.valobj.GetName()) + " seen as " + name_string)
        return wrapper


def CFArray_SummaryProvider(valobj, dict):
    logger = lldb.formatters.Logger.Logger()
    provider = NSArray_SynthProvider(valobj, dict)
    if not provider.invalid:
        if provider.error:
            return provider.wrapper.message()
        try:
            summary = int(provider.num_children())
        except:
            summary = None
        logger >> "provider gave me " + str(summary)
        if summary is None:
            summary = '<variable is not NSArray>'
        elif isinstance(summary, basestring):
            pass
        else:
            # we format it like it were a CFString to make it look the same as
            # the summary from Xcode
            summary = '@"' + str(summary) + \
                (" objects" if summary != 1 else " object") + '"'
        return summary
    return 'Summary Unavailable'


def __lldb_init_module(debugger, dict):
    debugger.HandleCommand(
        "type summary add -F CFArray.CFArray_SummaryProvider NSArray CFArrayRef CFMutableArrayRef")
