# -*- coding: utf-8 -*-
"""
 Copyright 2025 NXP

 NXP Confidential and Proprietary. This software is owned or controlled by NXP and may only be
 used strictly in accordance with the applicable license terms. By expressly
 accepting such terms or by downloading, installing, activating and/or otherwise
 using the software, you are agreeing that you have read, and that you agree to
 comply with and are bound by, such license terms. If you do not agree to be
 bound by the applicable license terms, then you may not retain, install,
 activate or otherwise use the software.

"""
import gdb
import os
    
class RegisterNameLookup:
    """
    Register name lookup with context-based lazy loading.
    """
    
    def __init__(self, verbose=True):
        """Initialize with lazy loading capabilities"""
        self.loaded_register_classes = {}
        self.verbose = verbose

    def get_address_by_name(self, name, context=None):
        """
        Get register address by name using context-specific register class
        """
        register_class = self._get_register_class_for_context(context)
        
        if register_class is None:
            if self.verbose:
                gdb.write("[S32Debugger]Warning: No register class available for context '{}'\n".format(context))
            return None
        
        address = register_class.get_address_by_name(name)
    
        if address is not None:
            if self.verbose:
                class_name = register_class.__class__.__name__
                gdb.write("[S32Debugger]Info: Register '{}' found in {} with address 0x{:08X}\n".format(name, class_name, address))
        else:
            if self.verbose:
                class_name = register_class.__class__.__name__
                gdb.write("[S32Debugger]Warning: Register '{}' not found in {}\n".format(name, class_name))
        
        return address    

    def is_register_available(self, name):
        """Check if a register name exists in any processor register class"""
        temp_verbose = self.verbose
        self.verbose = False
        result = self.get_address_by_name(name) is not None
        self.verbose = temp_verbose
        return result

    def _get_register_class_for_context(self, context):
        """
        Determine and load the appropriate register class based on context
        """
        if not context:
            if self.verbose:
                gdb.write("[S32Debugger]Info: No context provided, no register class loaded" + os.linesep)
            return None
        
        context_lower = context.lower()
        
        # Determine module/class based on context
        if 'cortexa' in context_lower:
            return self._load_class('arch.parmv8', 'ARMv8Registers', context)
        elif 'cortexr' in context_lower:
            return self._load_class('arch.parmv8r', 'ARMv8RRegisters', context)
        elif 'cortex-m' in context_lower:
            return self._load_class('arch.pcortexm', 'CortexMRegisters', context)
        elif 'zenv' in context_lower:
            return self._load_class('arch.pzenv', 'ZENVRegisters', context)
        elif 'spt3' in context_lower:
            return self._load_class('arch.pspt3', 'SPT3Registers', context)
        else:
            if self.verbose:
                 gdb.write("[S32Debugger]Warning: Unknown context '{}', no register class loaded\n".format(context))
            return None



    def _load_class(self, module_name, class_name, context=None):
        """Lazy load a register class"""
        cache_key = "{0}.{1}".format(module_name, class_name)
        
        if cache_key in self.loaded_register_classes:
            if self.verbose:
                if context:
                    gdb.write("[S32Debugger]Info: Context '{}' detected, using cached {} class\n".format(context, class_name))
                else:
                    gdb.write("[S32Debugger]Info: Using cached {} class\n".format(class_name))
            return self.loaded_register_classes[cache_key]
        
        try:
            if self.verbose:
                if context:
                    gdb.write("[S32Debugger]Info: Context '{}' detected, loading {} class\n".format(context, class_name))
                else:
                    gdb.write("[S32Debugger]Info: Loading module {} class {}\n".format(module_name, class_name))
            module = __import__(module_name, fromlist=[class_name])
            register_class = getattr(module, class_name)
            instance = register_class()
            self.loaded_register_classes[cache_key] = instance
            if self.verbose:
                gdb.write("[S32Debugger]Info: Successfully loaded {} class\n".format(class_name))
            return instance
        except Exception as e:
            if self.verbose:
                gdb.write("[S32Debugger]Warning: Failed to load {0}.{1}: {2}\n".format(module_name, class_name, e))
            self.loaded_register_classes[cache_key] = None
            return None


# Global register name lookup instance
register_lookup = RegisterNameLookup(verbose=False)
