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

import java.io.File;
import java.util.Properties;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.MockedStatic;

import CH.ifa.draw.DrawPlugin;
import CH.ifa.draw.IOHelper;
import CH.ifa.draw.application.DrawApplication;
import CH.ifa.draw.framework.DrawingView;
import CH.ifa.draw.util.GUIProperties;

import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

class ApplicationServiceImplTest {

    ApplicationServiceImpl _applicationService;

    @BeforeEach
    void setUp() {
        this._applicationService = new ApplicationServiceImpl();
    }

    @AfterEach
    void tearDown() {
        this._applicationService = null;
    }

    @ParameterizedTest
    @ValueSource(booleans = { true, false })
    void testSetDrawProperties(boolean value) {
        String valueS;
        valueS = booleanToString(value);
        //given:
        Properties properties = new Properties();
        properties.setProperty("draw", valueS);
        //when:
        _applicationService.setDrawProperties(properties);
        //then:
        assertThat(properties.getProperty("draw")).isEqualTo(valueS);
    }

    private static String booleanToString(boolean value) {
        String valueS;
        if (value) {
            valueS = "true";
        } else {
            valueS = "false";
        }
        return valueS;
    }


    @ParameterizedTest
    @ValueSource(booleans = { true, false })
    void testIsAvoidFrameReshape(boolean value) {
        //given:
        try (MockedStatic<GUIProperties> mocked = mockStatic(GUIProperties.class)) {
            mocked.when(GUIProperties::avoidFrameReshape).thenReturn(value);

            //when:
            _applicationService.isAvoidFrameReshape();
            //then:
            mocked.verify(GUIProperties::avoidFrameReshape);
            assertThat(_applicationService.isAvoidFrameReshape()).isEqualTo(value);
        }
    }

    @ParameterizedTest
    @ValueSource(booleans = { true, false })
    void testIsNoGraphics(boolean value) {
        //given:
        try (MockedStatic<GUIProperties> mocked = mockStatic(GUIProperties.class)) {
            mocked.when(GUIProperties::noGraphics).thenReturn(value);
            //when:
            boolean resultValue = _applicationService.isNoGraphics();
            //then:
            if (value) {
                assertThat(resultValue).isTrue();
            } else {
                assertThat(resultValue).isFalse();
            }
            mocked.verify(GUIProperties::noGraphics);
        }
    }

    @Test
    void testGetLastPath() {
        //given
        IOHelper ioHelper = mock(IOHelper.class);
        File expectedFile = new File("test.drw");
        when(ioHelper.getLastPath()).thenReturn(expectedFile);

        try (MockedStatic<IOHelper> mocked = mockStatic(IOHelper.class)) {
            mocked.when(IOHelper::getInstance).thenReturn(ioHelper);
            //when/then:
            assertThat(_applicationService.getLastPath()).isEqualTo(expectedFile);
        }
    }

    @ParameterizedTest
    @ValueSource(booleans = { true, false })
    void testCanClose(boolean value) {
        //given
        DrawApplication drawApplication = mock(DrawApplication.class);
        when(drawApplication.canClose()).thenReturn(value);
        try (MockedStatic<DrawPlugin> mocked = mockStatic(DrawPlugin.class)) {
            mocked.when(DrawPlugin::getGui).thenReturn(drawApplication);
            //when/then:
            if (value) {
                assertThat(_applicationService.canClose()).isTrue();
            } else {
                assertThat(_applicationService.canClose()).isFalse();
            }
        }
    }

    @ParameterizedTest
    @ValueSource(booleans = { true, false })
    void testRequestClose(boolean value) {
        //given:
        DrawApplication drawApplication = mock(DrawApplication.class);
        when(drawApplication.canClose()).thenReturn(value);
        try (MockedStatic<DrawPlugin> mocked = mockStatic(DrawPlugin.class)) {
            mocked.when(DrawPlugin::getGui).thenReturn(drawApplication);
            //when:
            _applicationService.requestClose();
            //then:
            if (value) {
                verify(drawApplication, times(1)).exit();
            } else {
                verify(drawApplication, times(0)).exit();
            }
        }
    }

    @Test
    void testShowStatus() {
        //given:
        DrawApplication drawApplication = mock(DrawApplication.class);
        try (MockedStatic<DrawPlugin> mocked = mockStatic(DrawPlugin.class)) {
            mocked.when(DrawPlugin::getGui).thenReturn(drawApplication);
            //when:
            _applicationService.showStatus("test");
            //then:
            verify(drawApplication, times(1)).showStatus("test");
        }
    }



    @Test
    void testRegisterDrawingViewFactory() {
        //given:
        DrawApplication drawApplication = mock(DrawApplication.class);
        Class<?> key = DrawingView.class;
        String id = "id";
        try (MockedStatic<DrawPlugin> mocked = mockStatic(DrawPlugin.class)) {
            mocked.when(DrawPlugin::getGui).thenReturn(drawApplication);
            //when:
            _applicationService.registerDrawingViewFactory(key, id);
            //then:
            verify(drawApplication, times(1)).registerDrawingViewFactoryID(key, id);
        }
    }
}
