print("SCCD NetLogo CLI interface")
import sys
import time
from sccd.runtime.statecharts_core import Event


def set_defaults(inp, defaultlist):
    for i, v in enumerate(defaultlist):
        if len(inp) == i + 1:
            inp.append(v)

def get_bool(val):
    if val.lower() in ["true", "yes", "1"]:
        return True
    else:
        return False

def poll_port(port):
    while 1:
        try:
            print(port.fetch(-1))
        except:
            pass

def raw_inputter():
    print("READY for input")
    print("Type 'help' for information")
    while 1:
        inp = raw_input().split(" ")
        action = inp[0]
        if inp[0] == "god_event":
            if len(inp) != 4:
                print("God Events require 3 parameters!")
                continue
            params = [{"turtle": inp[1], "attribute": inp[2], "value": inp[3]}]
        elif inp[0] in ["pause", "step", "continuous", "reset"]:
            params = []
        elif inp[0] == "realtime":
            set_defaults(inp, [1.0])
            params = [{"realtime_scale": float(inp[1])}]
        elif inp[0] == "exit" or inp[0] == "quit":
            break
        elif inp[0] == "add_breakpoint":
            if len(inp) < 5:
                print("Breakpoint removal requires 2 parameters!")
                continue
            # Merge together the final part again
            inp = [inp[0], inp[1], " ".join(inp[2:-2]).replace("\\n", "\n"), get_bool(inp[-2]), get_bool(inp[-1])]
            print("Generated parameters: " + str(inp))
            params = inp[1:]
        elif inp[0] == "del_breakpoint":
            if len(inp) < 2:
                print("Breakpoint removal requires 1 parameter!")
                continue
            params = [inp[1]]
        elif inp[0] == "enable_breakpoint":
            action = "toggle_breakpoint"
            params = [inp[1], True]
        elif inp[0] == "disable_breakpoint":
            action = "toggle_breakpoint"
            params = [inp[1], False]
        elif inp[0] == "help":
            print("Supported operations:")
            print("  continuous")
            print("   --> Simulate continuously")
            print("  step")
            print("   --> Simulate a single step")
            print("  god_event turtle_id attribute_name new_value")
            print("   --> Modify the internal state of an arbitrary turtle")
            print("       turtle_id should be a turtle id")
            print("       attribute_name is the name of the attribute to alter")
            print("       new_value is the value to assign")
            print("       new_value can only be a string due to string-only input")
            print("  add_breakpoint id function enabled disable_on_trigger")
            print("   --> Add a breakpoint that will pause simulation when function returns True")
            print("       the function should contain a definition of the 'breakpoint' function")
            print("       and must take 3 parameters: time, model and transitioned")
            print("       enabled indicates whether or not the breakpoint should be checked")
            print("       disable_on_trigger determines if the breakpoint should auto-disable")
            print("       after being triggered")
            print("  del_breakpoint id")
            print("   --> Remove a breakpoint")
            print("  enable_breakpoint id")
            print("   --> Enable the provided breakpoint")
            print("  disable_breakpoint id")
            print("   --> Disable the provided breakpoint")
            print("  reset")
            print("   --> Reset the simulation")
            print("  exit")
            print("   --> Stop the client")
            print("  pause")
            print("   --> Pause the simulation")
            print("  quit")
            print("   --> Stop the client")
            continue
        else:
            print("Command not understood: " + str(inp))
            continue
        controller.addInput(Event(action, "request", params))

import simulator
controller = simulator.Controller("BouncingBalls.nlogo")
reply_port = controller.addOutputListener('reply')
try:
    import threading

    thrd_o = threading.Thread(target=poll_port,args=[reply_port])
    thrd_o.daemon = True
    thrd_o.start()
    
    thrd_i = threading.Thread(target=raw_inputter)
    thrd_i.daemon = True
    thrd_i.start()

    controller.start()
finally:
    controller.stop()
