package de.gurkenlabs.litiengine.entities;

import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.Test;

public class EntityTests {

  @Test
  public void testEntityAction() {
    TestEntity entity = new TestEntity();

    assertTrue(entity.actions().exists("doSomething"));
    assertFalse(entity.actions().exists("imNotAnAction"));

    assertEquals(2, entity.actions().getActions().size());

    EntityAction action = entity.actions().get("doSomething");

    assertEquals("doSomething", action.getName());
    assertEquals("does something", action.getDescription());

    assertNotNull(action);

    action.perform();

    assertTrue(entity.didSomething);

    entity.actions().unregister(action);

    assertEquals(1, entity.actions().getActions().size());
    assertFalse(entity.actions().exists("doSomething"));

    entity.actions().register(action);

    assertEquals(2, entity.actions().getActions().size());
    assertTrue(entity.actions().exists("doSomething"));
  }

  @Test
  public void testNamedAction() {
    TestEntity entity = new TestEntity();

    assertTrue(entity.actions().exists("myName"));

    EntityAction action = entity.actions().get("myName");

    assertNotNull(action);

    action.perform();

    assertTrue(entity.didNamedAction);
  }

  @Test
  public void testCustomAction() {
    TestEntity entity = new TestEntity();
    entity.register("customAction", () -> {
      entity.customActionPerformed = true;
      return;
    });

    assertTrue(entity.actions().exists("customAction"));

    entity.perform("customAction");
    assertTrue(entity.customActionPerformed);

    entity.actions().unregister("customAction");

    assertFalse(entity.actions().exists("customAction"));

    assertDoesNotThrow(() -> entity.perform("I don't exist!"));
  }

  @Test
  public void testDefaultTags() {
    TestEntity entity = new TestEntity();

    assertTrue(entity.hasTag("some tag"));
    assertTrue(entity.hasTag("another tag"));
  }

  @Tag("some tag")
  @Tag("another tag")
  private class TestEntity extends Entity {
    private boolean didSomething;
    private boolean didNamedAction;
    private boolean customActionPerformed;

    @Action(description = "does something")
    public void doSomething() {
      didSomething = true;
    }

    @Action(name = "myName")
    public void namedAction() {
      didNamedAction = true;
    }

    @SuppressWarnings("unused")
    public void imNotAnAction() {
    }
    
    @Action
    public void imNotParameterless(int something) {
    }
    
    @Action
    private void privateAction() {
    }
  }
}

@@ -381,16 +381,206 @@
 pi.Test;
+%0Aimport org.junit.jupiter.params.ParameterizedTest;%0Aimport org.junit.jupiter.params.provider.Arguments;%0Aimport org.junit.jupiter.params.provider.MethodSource;%0Aimport java.util.stream.Stream;
 %0A%0Apublic
@@ -2248,36 +2248,83 @@
 st!%22));%0A  %7D%0A%0A  @
-Test
+ParameterizedTest%0A  @MethodSource(%22getDefaultTags%22)
 %0A  public void t
@@ -2338,16 +2338,26 @@
 ultTags(
+String tag
 ) %7B%0A    
@@ -2386,33 +2386,32 @@
 w TestEntity();%0A
-%0A
     assertTrue(e
@@ -2427,50 +2427,158 @@
 Tag(
-%22some 
 tag
-%22
 ));%0A  
-  assertTrue(entity.hasTag
+%7D%0A%0A  private static Stream%3CArguments%3E getDefaultTags() %7B%0A    return Stream.of(%0A            Arguments.of(%22some tag%22),%0A            Arguments.of
 (%22an
@@ -2588,16 +2588,21 @@
 er tag%22)
+%0A    
 );%0A  %7D%0A%0A

Remove test duplication from EntityTests