"""Default verb handler implementations."""

from __future__ import annotations

from h2g2.engine.game_object import GameObject, Flag
from h2g2.engine.state import GameState
from h2g2.engine.loop import verb_handler


@verb_handler("look")
def v_look(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    from h2g2.engine.loop import GameLoop
    old_prsa = state.prsa
    state.prsa = "look"
    GameLoop._describe_room_impl(state)
    state.prsa = old_prsa
    return True


@verb_handler("examine")
def v_examine(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    if prso is None:
        out.tell("What do you want to examine?\n")
        return True
    if prso.text:
        out.tell(prso.text + "\n")
    elif prso.ldesc:
        out.tell(prso.ldesc + "\n")
    else:
        out.tell(f"There's nothing special about {prso.the_desc()}.\n")
    # Show container contents
    if prso.fset_q(Flag.CONTBIT) or prso.fset_q(Flag.SURFACEBIT):
        if prso.fset_q(Flag.OPENBIT) or prso.fset_q(Flag.TRANSBIT):
            visible = prso.contents_string()
            if visible:
                out.tell(f"{prso.the_desc().capitalize()} contains:\n")
                for child in visible:
                    out.tell(f"  {child.a_desc()}\n")
    return True


@verb_handler("take")
def v_take(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    if prso is None:
        out.tell("What do you want to take?\n")
        return True

    if not prso.fset_q(Flag.TAKEBIT):
        out.tell(f"You can't take {prso.the_desc()}.\n")
        return True

    if prso.parent is state.protagonist:
        out.tell("You already have that.\n")
        return True

    prso.fset(Flag.TOUCHBIT)
    prso.move_to(state.protagonist)
    out.tell("Taken.\n")
    return True


@verb_handler("drop")
def v_drop(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    if prso is None:
        out.tell("What do you want to drop?\n")
        return True
    if not prso.is_held_by(state.protagonist):
        out.tell("You aren't carrying that.\n")
        return True
    prso.move_to(state.here)
    out.tell("Dropped.\n")
    return True


@verb_handler("inventory")
def v_inventory(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    if not state.protagonist or not state.protagonist.children:
        out.tell("You are empty-handed.\n")
        return True
    out.tell("You have:\n")
    for extra_fn in state.inventory_extras:
        line = extra_fn(state)
        if line:
            out.tell(f"  {line}\n")
    for obj in state.protagonist.children:
        desc = obj.a_desc()
        if obj.fset_q(Flag.WORNBIT):
            desc += " (being worn)"
        out.tell(f"  {desc}\n")
        # Show contents of containers
        if (obj.fset_q(Flag.CONTBIT) or obj.fset_q(Flag.SURFACEBIT)):
            visible = obj.contents_string()
            if visible and (obj.fset_q(Flag.OPENBIT) or obj.fset_q(Flag.TRANSBIT)):
                out.tell(f"  It looks like {obj.the_desc()} contains:\n")
                for child in visible:
                    out.tell(f"    {child.a_desc()}\n")
    return True


@verb_handler("put on")
def v_wear(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    if prso is None:
        out.tell("What do you want to wear?\n")
        return True
    if not prso.fset_q(Flag.WEARBIT):
        out.tell(f"You can't wear {prso.the_desc()}.\n")
        return True
    if not prso.is_held_by(state.protagonist):
        out.tell("You aren't carrying that.\n")
        return True
    prso.fset(Flag.WORNBIT)
    prso.move_to(state.protagonist)
    out.tell(f"You are now wearing {prso.the_desc()}.\n")
    return True


@verb_handler("take off")
def v_take_off(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    if prso is None:
        out.tell("What do you want to take off?\n")
        return True
    if not prso.fset_q(Flag.WORNBIT):
        out.tell("You aren't wearing that.\n")
        return True
    prso.fclear(Flag.WORNBIT)
    out.tell(f"You take off {prso.the_desc()}.\n")
    return True


@verb_handler("open")
def v_open(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    if prso is None:
        out.tell("What do you want to open?\n")
        return True
    if prso.fset_q(Flag.OPENBIT):
        out.tell("It's already open.\n")
        return True
    if not prso.fset_q(Flag.CONTBIT) and not prso.fset_q(Flag.DOORBIT):
        out.tell(f"You can't open {prso.the_desc()}.\n")
        return True
    prso.fset(Flag.OPENBIT)
    out.tell("Opened.\n")
    visible = prso.contents_string()
    if visible:
        for child in visible:
            out.tell(f"  {child.a_desc()}\n")
    return True


@verb_handler("close")
def v_close(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    if prso is None:
        out.tell("What do you want to close?\n")
        return True
    if not prso.fset_q(Flag.OPENBIT):
        out.tell("It's already closed.\n")
        return True
    prso.fclear(Flag.OPENBIT)
    out.tell("Closed.\n")
    return True


@verb_handler("put")
def v_put(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    if prso is None or prsi is None:
        out.tell("What do you want to put where?\n")
        return True
    if not prso.is_held_by(state.protagonist):
        out.tell("You aren't carrying that.\n")
        return True
    if not prsi.fset_q(Flag.CONTBIT) and not prsi.fset_q(Flag.SURFACEBIT):
        out.tell(f"You can't put things in {prsi.the_desc()}.\n")
        return True
    if not prsi.fset_q(Flag.OPENBIT) and prsi.fset_q(Flag.CONTBIT):
        out.tell(f"{prsi.the_desc().capitalize()} isn't open.\n")
        return True
    prso.move_to(prsi)
    out.tell("Done.\n")
    return True


@verb_handler("look in")
def v_look_in(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    if prso is None:
        out.tell("What do you want to look in?\n")
        return True
    if not prso.fset_q(Flag.CONTBIT) and not prso.fset_q(Flag.SURFACEBIT):
        out.tell(f"You can't look inside {prso.the_desc()}.\n")
        return True
    if not prso.fset_q(Flag.OPENBIT) and not prso.fset_q(Flag.TRANSBIT):
        out.tell(f"{prso.the_desc().capitalize()} is closed.\n")
        return True
    visible = prso.contents_string()
    if visible:
        for child in visible:
            out.tell(f"  {child.a_desc()}\n")
    else:
        out.tell(f"{prso.the_desc().capitalize()} is empty.\n")
    return True


@verb_handler("look under")
def v_look_under(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell(f"There's nothing under {prso.the_desc() if prso else 'that'}.\n")
    return True


@verb_handler("read")
def v_read(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    if prso is None:
        out.tell("What do you want to read?\n")
        return True
    if prso.text:
        out.tell(prso.text + "\n")
    else:
        out.tell(f"There's nothing written on {prso.the_desc()}.\n")
    return True


@verb_handler("wait")
def v_wait(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("Time passes.\n")
    return True


@verb_handler("turn on")
def v_turn_on(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    if prso is None:
        # Default: turn on light in the room
        out.tell("What do you want to turn on?\n")
        return True
    prso.fset(Flag.ONBIT)
    out.tell(f"You turn on {prso.the_desc()}.\n")
    state.update_lit()
    return True


@verb_handler("turn off")
def v_turn_off(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    if prso is None:
        out.tell("What do you want to turn off?\n")
        return True
    prso.fclear(Flag.ONBIT)
    out.tell(f"You turn off {prso.the_desc()}.\n")
    state.update_lit()
    return True


@verb_handler("get out")
def v_get_out(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    # Getting out of bed, vehicle, etc.
    # If prso is specified, delegate to its action handler
    if prso and prso.action:
        # Temporarily set the verb for the handler
        old_prsa = state.prsa
        state.prsa = "get out"
        result = prso.action(state)
        state.prsa = old_prsa
        if result:
            return True

    # Check if protagonist is inside something (bed, vehicle)
    if state.protagonist and state.protagonist.parent and state.protagonist.parent != state.here:
        container = state.protagonist.parent
        if container.action:
            old_prsa = state.prsa
            state.prsa = "get out"
            result = container.action(state)
            state.prsa = old_prsa
            if result:
                return True
        # Default: move out of container
        state.protagonist.move_to(state.here)
        state.lying_down = False
        state.output.tell("You get out.\n")
        return True

    state.output.tell("You're not in anything.\n")
    return True


@verb_handler("get in")
def v_get_in(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("You get in.\n")
    return True


@verb_handler("lie down")
def v_lie_down(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.lying_down = True
    state.output.tell("You lie down.\n")
    return True


@verb_handler("stand up")
def v_stand_up(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if not state.lying_down:
        state.output.tell("You're already standing.\n")
        return True
    state.lying_down = False
    state.output.tell("You stand up.\n")
    return True


@verb_handler("score")
def v_score(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    out.tell(f"Your score is {state.score} of a possible 400")
    out.tell(f", in {state.moves} turn{'s' if state.moves != 1 else ''}.\n")
    return True


@verb_handler("diagnose")
def v_diagnose(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    out = state.output
    if state.flags.get("headache"):
        out.tell("You have a big blinding throbber.\n")
    elif state.flags.get("groggy"):
        out.tell("You feel weak.\n")
    else:
        out.tell("You are in good health.\n")
    return True


@verb_handler("verbose")
def v_verbose(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.verbosity = 2
    state.output.tell("Maximum verbosity.\n")
    # Re-describe room
    state.prsa = "look"
    return True


@verb_handler("brief")
def v_brief(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.verbosity = 1
    state.output.tell("Brief descriptions.\n")
    return True


@verb_handler("superbrief")
def v_superbrief(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.verbosity = 0
    state.output.tell("Super-brief descriptions.\n")
    return True


@verb_handler("quit")
def v_quit(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("Thanks for playing!\n")
    state.running = False
    return True


@verb_handler("eat")
def v_eat(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("That's not edible.\n")
    return True


@verb_handler("drink")
def v_drink(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("You can't drink that.\n")
    return True


@verb_handler("sleep")
def v_sleep(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("You don't feel sleepy.\n")
    return True


@verb_handler("wake")
def v_wake(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("You are already awake.\n")
    return True


@verb_handler("listen")
def v_listen(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("You hear nothing special.\n")
    return True


@verb_handler("smell")
def v_smell(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("You smell nothing special.\n")
    return True


@verb_handler("taste")
def v_taste(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("That doesn't taste like anything.\n")
    return True


@verb_handler("touch")
def v_touch(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if prso:
        state.output.tell(f"You feel nothing unexpected about {prso.the_desc()}.\n")
    else:
        state.output.tell("You feel around in the dark.\n")
    return True


@verb_handler("shout")
def v_shout(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("Shouting gets you nowhere.\n")
    return True


@verb_handler("swim")
def v_swim(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("There's no water here.\n")
    return True


@verb_handler("pray")
def v_pray(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("Nothing happens.\n")
    return True


@verb_handler("attack")
def v_attack(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if prso:
        state.output.tell("Violence isn't the answer to this one.\n")
    else:
        state.output.tell("What do you want to attack?\n")
    return True


@verb_handler("give")
def v_give(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if prsi and prsi.action:
        result = prsi.action(state)
        if result:
            return True
    state.output.tell("No one is interested.\n")
    return True


@verb_handler("show")
def v_show(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if prsi and prsi.action:
        result = prsi.action(state)
        if result:
            return True
    state.output.tell("No one is interested.\n")
    return True


@verb_handler("tell")
def v_tell(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if prso and prso.action:
        result = prso.action(state)
        if result:
            return True
    state.output.tell("No one is listening.\n")
    return True


@verb_handler("ask")
def v_ask(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if prso and prso.action:
        result = prso.action(state)
        if result:
            return True
    state.output.tell("No one answers.\n")
    return True


@verb_handler("hang up")
def v_hang_up(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("You can't hang that up.\n")
    return True


@verb_handler("answer")
def v_answer(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("Nobody asked you a question.\n")
    return True


@verb_handler("call")
def v_call(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("There's no one to call.\n")
    return True


@verb_handler("consult")
def v_consult(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if prso and prso.action:
        result = prso.action(state)
        if result:
            return True
    state.output.tell("There's nothing useful to consult.\n")
    return True


@verb_handler("say")
def v_say(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("Talking to yourself is a sign of impending mental collapse.\n")
    return True


@verb_handler("carve")
def v_carve(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("Bizarre.\n")
    return True


@verb_handler("plug")
def v_plug(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if prso and prso.action:
        result = prso.action(state)
        if result:
            return True
    state.output.tell("You can't plug that in.\n")
    return True


@verb_handler("unplug")
def v_unplug(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if prso and prso.action:
        result = prso.action(state)
        if result:
            return True
    state.output.tell("It's not plugged in.\n")
    return True


@verb_handler("block")
def v_block(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("You can't block that.\n")
    return True


@verb_handler("rub")
def v_rub(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if prso:
        state.output.tell(f"Rubbing {prso.the_desc()} has no effect.\n")
    else:
        state.output.tell("What do you want to rub?\n")
    return True


@verb_handler("push")
def v_push(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if prso and prso.action:
        result = prso.action(state)
        if result:
            return True
    state.output.tell("Nothing happens.\n")
    return True


@verb_handler("hang")
def v_hang(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if prso and prso.action:
        result = prso.action(state)
        if result:
            return True
    state.output.tell("You can't hang that up.\n")
    return True


@verb_handler("repair")
def v_repair(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("You can't fix that.\n")
    return True


@verb_handler("follow")
def v_follow(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("You can't follow that.\n")
    return True


@verb_handler("kick")
def v_kick(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if prso:
        state.output.tell(f"Kicking {prso.the_desc()} has no effect.\n")
    else:
        state.output.tell("What do you want to kick?\n")
    return True


@verb_handler("knock")
def v_knock(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("Nobody's home.\n")
    return True


@verb_handler("type")
def v_type(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    if prso and prso.action:
        result = prso.action(state)
        if result:
            return True
    state.output.tell("There's nothing to type on.\n")
    return True


@verb_handler("enjoy")
def v_enjoy(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("I wouldn't dream of it.\n")
    return True


@verb_handler("panic")
def v_panic(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("DON'T PANIC!\n")
    return True


@verb_handler("relax")
def v_relax(state: GameState, prso: GameObject | None, prsi: GameObject | None) -> bool:
    state.output.tell("You feel calmer.\n")
    return True
