"""
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.
"""
# summary provider for CF(Mutable)BitVector
import lldb
import ctypes
import lldb.runtime.objc.objc_runtime
import lldb.formatters.metrics
import lldb.formatters.Logger

# first define some utility functions


def byte_index(abs_pos):
    logger = lldb.formatters.Logger.Logger()
    return abs_pos / 8


def bit_index(abs_pos):
    logger = lldb.formatters.Logger.Logger()
    return abs_pos & 7


def get_bit(byte, index):
    logger = lldb.formatters.Logger.Logger()
    if index < 0 or index > 7:
        return None
    return (byte >> (7 - index)) & 1


def grab_array_item_data(pointer, index):
    logger = lldb.formatters.Logger.Logger()
    return pointer.GetPointeeData(index, 1)

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 a CF*BitVector, so they need not
# obey the interface specification for synthetic children providers


class CFBitVectorKnown_SummaryProvider:

    def adjust_for_architecture(self):
        logger = lldb.formatters.Logger.Logger()
        self.uiint_size = self.sys_params.types_cache.NSUInteger.GetByteSize()
        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.NSUInteger):
            if self.sys_params.is_64_bit:
                self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
                ).GetBasicType(lldb.eBasicTypeUnsignedLong)
            else:
                self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
                ).GetBasicType(lldb.eBasicTypeUnsignedInt)
        if not(self.sys_params.types_cache.charptr):
            self.sys_params.types_cache.charptr = self.valobj.GetType(
            ).GetBasicType(lldb.eBasicTypeChar).GetPointerType()
        self.update()

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

    # we skip the CFRuntimeBase
    # then the next CFIndex is the count
    # then we skip another CFIndex and then we get at a byte array
    # that wraps the individual bits

    def contents(self):
        logger = lldb.formatters.Logger.Logger()
        count_vo = self.valobj.CreateChildAtOffset(
            "count",
            self.sys_params.cfruntime_size,
            self.sys_params.types_cache.NSUInteger)
        count = count_vo.GetValueAsUnsigned(0)
        if count == 0:
            return '(empty)'

        array_vo = self.valobj.CreateChildAtOffset(
            "data",
            self.sys_params.cfruntime_size +
            2 *
            self.uiint_size,
            self.sys_params.types_cache.charptr)

        data_list = []
        cur_byte_pos = None
        for i in range(0, count):
            if cur_byte_pos is None:
                cur_byte_pos = byte_index(i)
                cur_byte = grab_array_item_data(array_vo, cur_byte_pos)
                cur_byte_val = cur_byte.uint8[0]
            else:
                byte_pos = byte_index(i)
                # do not fetch the pointee data every single time through
                if byte_pos != cur_byte_pos:
                    cur_byte_pos = byte_pos
                    cur_byte = grab_array_item_data(array_vo, cur_byte_pos)
                    cur_byte_val = cur_byte.uint8[0]
            bit = get_bit(cur_byte_val, bit_index(i))
            if (i % 4) == 0:
                data_list.append(' ')
            if bit == 1:
                data_list.append('1')
            else:
                data_list.append('0')
        return ''.join(data_list)


class CFBitVectorUnknown_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 contents(self):
        logger = lldb.formatters.Logger.Logger()
        return '<unable to summarize this CFBitVector>'


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()
    actual_name = name_string

    logger >> "name string got was " + \
        str(name_string) + " but actual name is " + str(actual_name)

    if class_data.is_cftype():
        # CFBitVectorRef does not expose an actual NSWrapper type, so we have to check that this is
        # an NSCFType and then check we are a pointer-to CFBitVectorRef
        valobj_type = valobj.GetType()
        if valobj_type.IsValid() and valobj_type.IsPointerType():
            valobj_type = valobj_type.GetPointeeType()
            if valobj_type.IsValid():
                actual_name = valobj_type.GetName()
        if actual_name == '__CFBitVector' or actual_name == '__CFMutableBitVector':
            wrapper = CFBitVectorKnown_SummaryProvider(
                valobj, class_data.sys_params)
            statistics.metric_hit('code_notrun', valobj)
        else:
            wrapper = CFBitVectorUnknown_SummaryProvider(
                valobj, class_data.sys_params)
            print actual_name
    else:
        wrapper = CFBitVectorUnknown_SummaryProvider(
            valobj, class_data.sys_params)
        print name_string
        statistics.metric_hit(
            'unknown_class',
            valobj.GetName() +
            " seen as " +
            name_string)
    return wrapper


def CFBitVector_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.contents()
        except:
            summary = None
        logger >> "summary got from provider: " + str(summary)
        if summary is None or summary == '':
            summary = '<variable is not CFBitVector>'
        return summary
    return 'Summary Unavailable'


def __lldb_init_module(debugger, dict):
    debugger.HandleCommand(
        "type summary add -F CFBitVector.CFBitVector_SummaryProvider CFBitVectorRef CFMutableBitVectorRef")
