import gdb
import json
from common.config import RegisterStacking, Symbol, Reg
from common.util import safe_gdb_lookup_type, arm_32_commmon_registers
from common.Rtos import Rtos


class RtosDetector(gdb.Function):

    def __init__(self):
        super(RtosDetector, self).__init__("rtos_init")

    def invoke(self, rtos_name):
        rtos_name_str = rtos_name.string()
        if rtos_name_str == "AUTO":
            rtos = find_rtos()
        else:
            rtos = find_rtos(rtos_name_str)

        if rtos is not None:
            init_rtos(rtos)

        if config.curr_rtos is not None:
            return json.dumps({
                'name': config.curr_rtos.name(),
            })
        else:
            return json.dumps({
                'name': '',
            })


def find_rtos(name=None):
    for r in config.rtos_list:
        if name is not None and r.name().lower() != name.lower():
            continue
        if r.detect():
            return r
    return None


def init_rtos(rtos):  # rtos: Rtos
    SwitchBack()
    SwitchRtosThread()
    GetTasks()
    GetCurrentTask()
    GetQueueData()
    GetTimers()
    GetHeapInfo()
    GetConfig()
    config.curr_rtos = rtos()


class SwitchBack(gdb.Function):

    def __init__(self):
        super(SwitchBack, self).__init__("rtos_switch_back")

    def invoke(self):
        config.curr_rtos.switch_thread_back()
        return gdb.Value(1)


class SwitchRtosThread(gdb.Function):

    def __init__(self):
        super(SwitchRtosThread, self).__init__("rtos_switch_thread")

    def invoke(self, stack_addr):
        config.curr_rtos.switch_thread(stack_addr)
        return gdb.Value(1)


class GetTasks(gdb.Function):

    def __init__(self):
        super(GetTasks, self).__init__("rtos_tasks")

    def invoke(self):
        return config.curr_rtos.get_threads()


class GetCurrentTask(gdb.Function):

    def __init__(self):
        super(GetCurrentTask, self).__init__("rtos_curr")

    def invoke(self):
        return config.curr_rtos.get_current_thread()


class GetQueueData(gdb.Function):
    def __init__(self):
        super(GetQueueData, self).__init__("rtos_queue")

    def invoke(self):
        return config.curr_rtos.get_queues()


class GetTimers(gdb.Function):
    def __init__(self):
        super(GetTimers, self).__init__("rtos_timers")

    def invoke(self):
        return config.curr_rtos.get_timers()


class GetHeapInfo(gdb.Function):
    def __init__(self):
        super(GetHeapInfo, self).__init__("rtos_heap")

    def invoke(self):
        return config.curr_rtos.get_heap_info()


class GetConfig(gdb.Function):
    def __init__(self):
        super(GetConfig, self).__init__("rtos_config")

    def invoke(self):
        return config.curr_rtos.get_config()


def rtos_class(cls):
    if not issubclass(cls, Rtos):
        raise ValueError("Only classes inheriting Rtos class can be annotated with @rtos_class")
    config.rtos_list.append(cls)
    return cls


RtosDetector()
