package com.github.bjoernpetersen.jmusicbot.playback;

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.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;

import com.github.bjoernpetersen.jmusicbot.Song;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nonnull;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

class PlayerStateTest {

  @Nonnull
  private static Song mockSong() {
    return mock(Song.class);
  }

  @Test
  void play() {
    Song song = mockSong();
    PlayerState state = PlayerState.play(song);

    assertSame(PlayerState.State.PLAY, state.getState());
    Optional<Song> songOptional = state.getSong();
    assertTrue(songOptional.isPresent());
    assertEquals(song, songOptional.get());
    assertSame(song, songOptional.get());
  }

  @Test
  void playNullSong() {
    assertThrows(NullPointerException.class, () -> PlayerState.play(null));
  }

  @Test
  void pause() {
    Song song = mockSong();
    PlayerState state = PlayerState.pause(song);

    assertSame(PlayerState.State.PAUSE, state.getState());
    Optional<Song> songOptional = state.getSong();
    assertTrue(songOptional.isPresent());
    assertEquals(song, songOptional.get());
    assertSame(song, songOptional.get());
  }

  @Test
  void pauseNullSong() {
    assertThrows(NullPointerException.class, () -> PlayerState.pause(null));
  }

  @Test
  void stop() {
    assertSame(PlayerState.State.STOP, PlayerState.stop().getState());
  }

  @Test
  void stopNoSong() {
    assertFalse(PlayerState.stop().getSong().isPresent());
  }

  @Test
  void error() {
    assertSame(PlayerState.State.ERROR, PlayerState.error().getState());
  }

  @Test
  void errorNoSong() {
    assertFalse(PlayerState.error().getSong().isPresent());
  }

  @SuppressWarnings("unused") // used as MethodSource
  private static List<PlayerState> getPossibleStates() {
    Song song = mockSong();
    return Arrays.asList(
        PlayerState.play(song), PlayerState.pause(song),
        PlayerState.stop(), PlayerState.error()
    );
  }

  @ParameterizedTest
  @MethodSource(names = "getPossibleStates")
  void getSongNotNull(PlayerState state) {
    assertNotNull(state.getSong());
  }
}

@@ -447,24 +447,83 @@
 kito.mock;%0A%0A
+import com.github.bjoernpetersen.jmusicbot.EqualsContract;%0A
 import com.g
@@ -831,17 +831,78 @@
 ateTest 
-%7B
+implements EqualsContract%3CPlayerState%3E %7B%0A%0A  private Song song;
 %0A%0A  @Non
@@ -2715,11 +2715,661 @@
 ());%0A  %7D
+%0A%0A  @Nonnull%0A  @Override%0A  public PlayerState createValue() %7B%0A    song = mockSong();%0A    return PlayerState.play(song);%0A  %7D%0A%0A  @Override%0A  public int getEqualRelevantValueCount() %7B%0A    return 5;%0A  %7D%0A%0A  @Nonnull%0A  @Override%0A  public PlayerState createNotEqualValue(int valueIndex) %7B%0A    switch (valueIndex) %7B%0A      case 0:%0A        return PlayerState.play(mockSong());%0A      case 1:%0A        return PlayerState.pause(song);%0A      case 2:%0A        return PlayerState.pause(mockSong());%0A      case 3:%0A        return PlayerState.stop();%0A      case 4:%0A        return PlayerState.error();%0A      default:%0A        throw new IllegalArgumentException();%0A    %7D%0A  %7D
 %0A%7D%0A

Test equals contract for PlayerState