from time import sleep
from Antmicro import Renode

def mc_uart_connect(device):
    def __printer(b):
        sys.stdout.write(chr(b))

    uart = None
    device_name = device.GetName()
    try:
        uart = clr.Convert(device, Renode.Peripherals.UART.IUART)
    except:
        print("Peripheral %s is not an IUART." % device_name)
        return 1

    print("Redirecting the input to %s, press <ESC> to quit..." % device_name)
    uart.CharReceived += __printer
    while True:
       c = sys.stdin.read(1)
       if ord(c) == 27:
           break
       uart.WriteChar(ord(c))
    uart.CharReceived -= __printer
    print("Disconnected from %s" % device_name)

def mc_next_value(offset = 0):
    print "%d" % (mc_next_value.current_value + offset)
    mc_next_value.current_value = mc_next_value.current_value + 1

mc_next_value.current_value = 0

def mc_sleep(time):
    sleep(float(time))

def mc_console_log(string):
    System.Console.WriteLine(string)

def mc_echo(*value):
    if len(value) == 2:
        if value[0] == "-n":
            sys.stdout.write(value[1])
            return
    elif len(value) == 1:
        print value[0]
        return
    elif len(value) == 0:
        print
        return
    print "usage: echo [-n] [string]"

def mc_dump(mem_start_val, mem_count_val, wid_val = 16):
    wid = int(wid_val)
    sysbus = self.Machine["sysbus"]
    mem_start = int(mem_start_val)
    mem_count = int(mem_count_val)
    for a in range(mem_start, mem_start + mem_count, wid):
        data = sysbus.ReadBytes(a, wid)
        print "0x%08X |" % a,
        for b in range(0, wid):
            print "%02X" % data[b] ,
        print "| " ,
        for b in range(0, wid):
            c = data[b]
            if not ((c < 0x20) or (c > 127)):
                print "%c%c" % (chr(8), chr(c)) ,
            else:
                print "%c." % chr(8) ,
        print

def mc_dump_file(mem_start_val, mem_count_val, filename):
    sysbus = self.Machine["sysbus"]
    mem_start = int(mem_start_val)
    mem_count = int(mem_count_val)
    tab = sysbus.ReadBytes(mem_start, mem_count)
    fl = System.IO.FileStream(filename, System.IO.FileMode.Create, System.IO.FileAccess.Write)
    fl.Write(tab, 0, mem_count)
    fl.Close()

def mc_get_environ(variable):
    v = System.Environment.GetEnvironmentVariable(variable)
    if v != None:
        print v

def mc_if(condition, cmd):
    if condition:
        for line in cmd.splitlines():
            monitor.Parse(line)

def mc_str_contains(a, b):
        print a.lower() in b.lower()

def mc_print(*fmt, **kwargs):
    logLevels = {
        -1: LogLevel.Noisy,
        0: LogLevel.Debug,
        1: LogLevel.Info,
        2: LogLevel.Warning,
        3: LogLevel.Error,
    }
    sep = ' '
    if 'sep' in kwargs:
        sep = kwargs['sep']
    if 'log' in kwargs and kwargs['log'] in logLevels:
        Renode.Logging.Logger.Log(logLevels[kwargs['log']], sep.join(map(str, fmt)))
    else:
        print sep.join(map(str, fmt))

def mc_pyprint(script):
    print eval(script)

externals = type('ExternalsManagerAccessor', (object,), dict(
    __getitem__ = lambda _, name: Renode.Core.Structure.IHasChildren[Renode.Core.IExternal].TryGetByName(emulationManager.CurrentEmulation.ExternalsManager, name)[0],
    __getattr__ = lambda self, name: self.__getitem__(name),
))()

variables = type('MonitorVariablesAccessor', (object,), dict(
    __getitem__ = lambda _, name: monitor.GetVariable(name),
    __getattr__ = lambda self, name: self.__getitem__(name),
))()
