package de.renew.draw.ui.impl.services;

import java.util.Vector;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import CH.ifa.draw.standard.FigureException;
import de.renew.draw.storables.ontology.Drawing;
import de.renew.draw.storables.ontology.Figure;
import de.renew.draw.ui.ontology.ErrorState;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;

public class ErrorServiceImplTest {

    private static final String DUMMY_STRING = "Dummy String";
    private static final int DUMMY_INT = 123;
    private static final Drawing DUMMY_DRAWING = mock(Drawing.class);
    private static final Figure DUMMY_FIGURE = mock(Figure.class);
    private static final Object DUMMY_OBJECT = mock(Object.class);

    private ErrorServiceImpl _service;
    private Vector<Figure> _figures;

    @BeforeEach
    void setUp() {
        _service = new ErrorServiceImpl();
        _figures = new Vector<>();
        _figures.add(DUMMY_FIGURE);
    }

    @AfterEach
    void tearDown() {
        _service = null;
        _figures = null;
    }

    @Test
    void testCreateErrorStateWithSingleFigure() {
        // given
        FigureException expected =
            new FigureException(DUMMY_STRING, DUMMY_STRING, DUMMY_DRAWING, DUMMY_FIGURE);

        // when
        ErrorState actual =
            _service.createErrorState(DUMMY_STRING, DUMMY_STRING, DUMMY_DRAWING, DUMMY_FIGURE);

        // then
        assertThat(actual.getTitle()).isEqualTo(expected.getTitle());
        assertThat(actual.getMessage()).isEqualTo(expected.getMessage());
        assertThat(actual.getErroneousDrawing()).isPresent().containsSame(DUMMY_DRAWING);
        assertThat(actual.getErroneousFigures())
            .containsExactlyElementsOf(expected.getErroneousFigures());
    }

    @Test
    void testCreateErrorStateWithMultipleFigures() {
        // given
        FigureException expected =
            new FigureException(DUMMY_STRING, DUMMY_STRING, DUMMY_DRAWING, _figures);

        // when
        ErrorState actual =
            _service.createErrorState(DUMMY_STRING, DUMMY_STRING, DUMMY_DRAWING, _figures);

        // then
        assertThat(actual.getTitle()).isEqualTo(expected.getTitle());
        assertThat(actual.getMessage()).isEqualTo(expected.getMessage());
        assertThat(actual.getErroneousDrawing()).isPresent().containsSame(DUMMY_DRAWING);
        assertThat(actual.getErroneousFigures()).containsExactlyElementsOf(_figures);
    }

    @Test
    void testCreateErrorStateWithMultipleFiguresAndObject() {
        // given
        FigureException expected = new FigureException(
            DUMMY_STRING, DUMMY_INT, DUMMY_INT, DUMMY_DRAWING, DUMMY_FIGURE, _figures,
            DUMMY_OBJECT);

        // when
        ErrorState actual = _service.createErrorState(
            DUMMY_STRING, DUMMY_INT, DUMMY_INT, DUMMY_DRAWING, DUMMY_FIGURE, _figures,
            DUMMY_OBJECT);

        // then
        assertThat(actual.getMessage()).isEqualTo(expected.getMessage());
        assertThat(actual.getLine()).isEqualTo(expected.getLine());
        assertThat(actual.getColumn()).isEqualTo(expected.getColumn());
        assertThat(actual.getErroneousDrawing()).isPresent().containsSame(DUMMY_DRAWING);
        assertThat(actual.getErroneousFigures()).containsExactlyElementsOf(_figures);
        assertThat(actual.getErroneousFigure(Figure.class)).isPresent().containsSame(DUMMY_FIGURE);
        assertThat(actual.getProblemSpecificInformation()).isPresent().containsSame(DUMMY_OBJECT);
    }

    @Test
    void testCreateErrorStateWithSingleFigureAndObject() {
        // given
        FigureException expected = new FigureException(
            DUMMY_STRING, DUMMY_INT, DUMMY_INT, DUMMY_DRAWING, DUMMY_FIGURE, DUMMY_OBJECT);

        // when
        ErrorState actual = _service.createErrorState(
            DUMMY_STRING, DUMMY_INT, DUMMY_INT, DUMMY_DRAWING, DUMMY_FIGURE, DUMMY_OBJECT);

        // then
        assertThat(actual.getMessage()).isEqualTo(expected.getMessage());
        assertThat(actual.getLine()).isEqualTo(expected.getLine());
        assertThat(actual.getColumn()).isEqualTo(expected.getColumn());
        assertThat(actual.getErroneousDrawing()).isPresent().containsSame(DUMMY_DRAWING);
        assertThat(actual.getErroneousFigure(Figure.class)).isPresent().containsSame(DUMMY_FIGURE);
        assertThat(actual.getProblemSpecificInformation()).isPresent().containsSame(DUMMY_OBJECT);
    }
}
