package thb.jeanluc.adventure.game;

import org.junit.jupiter.api.Test;
import thb.jeanluc.adventure.io.TestIO;
import thb.jeanluc.adventure.model.Effect;
import thb.jeanluc.adventure.model.Player;
import thb.jeanluc.adventure.model.Room;
import thb.jeanluc.adventure.model.World;
import thb.jeanluc.adventure.model.item.Item;
import thb.jeanluc.adventure.model.item.PlainItem;

import java.util.List;
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;

class EffectsTest {
    private GameContext ctx(Map<String, Item> items) {
        Player p = new Player(new Room("k", "K", "d"), 0);
        World w = new World(Map.of(), items, Map.of(), "t", "w");
        return new GameContext(w, p, new TestIO());
    }

    @Test
    void setAndClearFlag() {
        GameContext ctx = ctx(Map.of());
        Effects.applyAll(List.of(new Effect(Effect.Type.SET_FLAG, "power_on")), ctx);
        assertThat(ctx.getState().isSet("power_on")).isTrue();
        Effects.apply(new Effect(Effect.Type.CLEAR_FLAG, "power_on"), ctx);
        assertThat(ctx.getState().isSet("power_on")).isFalse();
    }

    @Test
    void giveAndRemoveItem() {
        Item key = PlainItem.builder().id("key").name("Key").description("d").build();
        GameContext ctx = ctx(Map.of("key", key));
        Effects.apply(new Effect(Effect.Type.GIVE_ITEM, "key"), ctx);
        assertThat(ctx.getPlayer().hasItem("key")).isTrue();
        Effects.apply(new Effect(Effect.Type.REMOVE_ITEM, "key"), ctx);
        assertThat(ctx.getPlayer().hasItem("key")).isFalse();
    }

    @Test
    void giveUnknownItemIsTolerated() {
        GameContext ctx = ctx(Map.of());
        Effects.apply(new Effect(Effect.Type.GIVE_ITEM, "ghost"), ctx);
        assertThat(ctx.getPlayer().hasItem("ghost")).isFalse();
    }

    @Test
    void sayWritesToIo() {
        GameContext ctx = ctx(Map.of());
        Effects.apply(new Effect(Effect.Type.SAY, "boo"), ctx);
        assertThat(((TestIO) ctx.getIo()).allOutput()).contains("boo");
    }

    @Test
    void startQuestStartsQuestInLog() {
        GameContext ctx = ctx(Map.of());
        Effects.apply(new Effect(Effect.Type.START_QUEST, "restore_power"), ctx);
        assertThat(ctx.getQuestLog().isActive("restore_power")).isTrue();
    }
}
