package de.accso.flexinale.common.infrastructure.eventbus;

import de.accso.flexinale.common.api.eventbus.EventContextHolder;
import de.accso.flexinale.common.api.event.EventContext;
import de.accso.flexinale.common.shared_kernel.DeveloperMistakeException;
import de.accso.flexinale.common.shared_kernel.Identifiable;
import org.junit.jupiter.api.Test;

import java.util.Collections;

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

class InMemorySyncEventContextHolderTest {

    @Test
    void testInitialHolderDoesNotContainAnything() {
        // arrange
        EventContextHolder sut = new InMemorySyncEventContextHolder();

        // act
        EventContext eventContext = sut.get();

        // assert
        assertThat(eventContext).isNull();
    }

    @Test
    void testSetAndGetOnce() {
        // arrange
        EventContextHolder sut = new InMemorySyncEventContextHolder();
        EventContext newContext = new EventContext(Identifiable.Id.of("123"), Collections.emptyList());

        // act
        sut.set(newContext);
        EventContext eventContext = sut.get();

        // assert
        assertThat(eventContext).isEqualTo(newContext);

        // act
        sut.remove();
        eventContext = sut.get();

        // assert
        assertThat(eventContext).isNull();
    }

    @Test
    void testSetAndGetTwice() {
        // arrange
        EventContextHolder sut = new InMemorySyncEventContextHolder();
        EventContext newContext = new EventContext(Identifiable.Id.of("123"), Collections.emptyList());

        // act set twice
        sut.set(newContext);
        sut.set(newContext);

        // assert
        assertThat(sut.get()).isEqualTo(newContext);

        // act remove first time
        sut.remove();

        // assert
        assertThat(sut.get()).isEqualTo(newContext);

        // act second first time
        sut.remove();

        // assert
        assertThat(sut.get()).isNull();
    }

    @Test
    void testRemoveOnceToOftenIsAnError() {
        // arrange
        int maxSets = 10;

        EventContextHolder sut = new InMemorySyncEventContextHolder();
        EventContext newContext = new EventContext(Identifiable.Id.of("123"), Collections.emptyList());

        // act
        for (int i=0; i<maxSets; i++) {
            sut.set(newContext);
        }

        // assert
        assertThat(sut.get()).isEqualTo(newContext);

        // act
        for (int i=0; i<maxSets; i++) {
            sut.remove();
        }

        // assert
        assertThat(sut.get()).isNull();

        // assert error second time
        assertThatThrownBy(() -> {
            sut.remove();
        }).isInstanceOf(DeveloperMistakeException.class)
        .hasMessageContaining("remove on InMemorySyncEventContextHolder once too much, should not happen");
    }
}