import time

from imitator_plugins import (
    hook, set_blocking_io, set_non_blocking_io,
    NextType, StateType, jprint,
    TermIO, jput, nonblockingio, check_ctrl_c
)

e = "\b \b"

def clear():
    jprint("\033[2J\033[H")

def anyinput():
    set_blocking_io()
    check_ctrl_c()
    set_non_blocking_io()

@hook("on_start")
def on_start(next: NextType, state: StateType):
    state["mode"] = "interactive"
    return next(state)

@nonblockingio
def print(s: str, sleep: float):
    while s:
        check_ctrl_c()
        jput(s[0])
        s = s[1:]
        time.sleep(sleep)

@hook("init")
def init(_: NextType, state: StateType):
    state["_io_mode_is_blocking"] = True
    state["_last_was_n"] = False

    clear()

    # antraction
    introducion = "Storyteller v0.1: read a story inside your terminal"
    _len = len(introducion)
    print(introducion, 0.01)
    time.sleep(1)
    print(e*_len, 0.01)

    time.sleep(0.2)

    usage = "Storyteller will automatically stop after every paragraph to let you read it full"
    _len = len(usage)
    print(usage, 0.01)
    time.sleep(0.5)

    jput("\n")

    i_see = "+ I see"
    i_see_len = len(i_see)
    print(i_see, 0.01)
    anyinput()

    print(e*i_see_len, 0.01)
    jput("\033[A")
    jput(f"\033[{_len}C")
    print(e*_len, 0.01)

    time.sleep(1)
    print("loading story", 0.01)
    time.sleep(0.5)
    print(" (xd no)", 0.005)
    time.sleep(0.5)
    jprint("\n *")

    states = ["/", "-", "\\", "|"]
    set_non_blocking_io()
    for _state in states*10:
        jput("\b" + str(_state))
        if TermIO.getch() == "\x03":
            raise KeyboardInterrupt("interrupted by user")
        time.sleep(0.1)

    clear()

    return state

@hook("instead")
def instead(_: NextType, state: StateType):
    if state["_val"] == "\n" and not state["_last_was_n"]:
        anyinput()
        state["_last_was_n"] = True
    elif state["_val"] != "\n":
        state["_last_was_n"] = False
    jput(state["_val"])
    return state

@hook("instead")
def basic_instead(next: NextType, state: StateType):
    state["_val"] = state["content"][0]
    state["content"] = state["content"][1:]
    return next(state)

@hook("after")
def after(_: NextType, state: StateType):
    time.sleep(state["delay"])
    if len(state["content"]) == 0:
        state["exit"] = True
    return state

@hook("on_interrupt_occur")
def on_interrupt(next: NextType, state: StateType):
    clear()
    jprint("The story only continues...\n")
    return next(state)
