from utils import Logger, LivePlotter
from nmotion_transport import Actuator, IMU, Driver, NCoder, USBInterface, getCurrentLibraryVersion
from device_manager import DeviceManager
import IPython
import gc

CLI_VERSION = "0.1.6-beta"

def __print_banner():
    print(f'NMotion CLI Tool v{CLI_VERSION} ({getCurrentLibraryVersion()})')
    print('Please connect your NMotion Component via NLink device.')
    print('You can also type help() or quit().')

def __on_new_device_callback(dev_identifier: str, interface: USBInterface) -> None:
    dev_id, dev_type, stripped_iface_name = dev_identifier.split("::")
    dev_id = int(dev_id)
    dev_type = int(dev_type)

    if(not interface.isDevice()):
        if(dev_type == 1):
            __logger.notify(f"New Device with ID: {dev_id} got connected. Actuator_{dev_id}_{stripped_iface_name} object created.")
            globals()[f'Actuator_{dev_id}_{stripped_iface_name}'] = Actuator(dev_id, interface) 
        elif(dev_type == 2):
            __logger.notify(f"New Device with ID: {dev_id} got connected. Driver_{dev_id}_{stripped_iface_name} object created.")
            globals()[f'Driver_{dev_id}_{stripped_iface_name}'] = Driver(dev_id, interface)     
        elif(dev_type == 3):
            __logger.notify(f"New Device with ID: {dev_id} got connected. IMU_{dev_id}_{stripped_iface_name} object created.")
            globals()[f'IMU_{dev_id}_{stripped_iface_name}'] = IMU(dev_id, interface)     
        elif (dev_type == 4):
            __logger.notify(f"New Device with ID: {dev_id} got connected. NCoder_{dev_id}_{stripped_iface_name} object created.")
            globals()[f'NCoder_{dev_id}_{stripped_iface_name}'] =  NCoder(dev_id, interface) 
        else:
            __logger.warn(f'Unknown Device of type {dev_type} with ID: {dev_id} got connected. No object will be created.')
    else:
        if(dev_type == 2):
            globals()[f'Driver_{dev_id}_{stripped_iface_name}'] = Driver(interface=interface)
            __logger.notify(f"New Device with ID: {dev_id} got connected. Driver_{dev_id}_{stripped_iface_name} object created.")
        elif(dev_type == 3):
            globals()[f'IMU_{dev_id}_{stripped_iface_name}'] = IMU(interface=interface)
            __logger.notify(f"New Device with ID: {dev_id} got connected. IMU_{dev_id}_{stripped_iface_name} object created.")
        elif(dev_type == 4):
            globals()[f'NCoder_{dev_id}_{stripped_iface_name}'] =  NCoder(interface=interface)
            __logger.notify(f"New Device with ID: {dev_id} got connected. NCoder_{dev_id}_{stripped_iface_name} object created.")
        else:
            __logger.warn(f'Unknown Device of type {dev_type} with ID: {dev_id} got connected. No object will be created.')


def __on_remove_device_callback(dev_identifier: str) -> None:
    global __console
    dev_id, dev_type, stripped_iface_name = dev_identifier.split("::")
    dev_id = int(dev_id)
    dev_type = int(dev_type)

    obj_to_delete = None

    if(dev_type == 1):
        obj_to_delete = f'Actuator_{dev_id}_{stripped_iface_name}'
    elif(dev_type == 2):
        obj_to_delete = f'Driver_{dev_id}_{stripped_iface_name}'
    elif(dev_type == 3):
        obj_to_delete = f'IMU_{dev_id}_{stripped_iface_name}'
    elif(dev_type == 4):
        obj_to_delete = f'NCoder_{dev_id}_{stripped_iface_name}'
    
    if(obj_to_delete):
        # Delete object from both globals and userspace
        del globals()[obj_to_delete]
        __console.user_ns.pop(obj_to_delete, None)
        __logger.warn(f"Device with ID: {dev_id} is removed.")
    
    # Delete all objects with 0 reference counts
    gc.collect()

    

if __name__ == '__main__':
    __print_banner()
    
    # Create required global variables
    __logger = Logger()
    __devManager = DeviceManager(__logger, __on_new_device_callback, __on_remove_device_callback)
    plotter = LivePlotter(__logger)
      
    # Create and Start shell
    __console = IPython.terminal.embed.InteractiveShellEmbed(banner1='')
    __console()
    
    # Stop all threads and exit
    __devManager.stopThreads()
    
    