package org.jboss.installer.validators;

import org.jboss.installer.core.LanguageUtils;
import org.jboss.installer.core.ValidationResult;
import org.jboss.installer.postinstall.task.JsfLibraryTask;
import org.jboss.installer.test.utils.MockLanguageUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;

import java.net.URL;
import java.nio.file.Paths;
import java.util.jar.JarFile;

import static org.assertj.core.api.Assertions.assertThat;
import static org.jboss.installer.postinstall.task.JsfLibraryTask.Config.JsfProject.Mojarra;
import static org.jboss.installer.postinstall.task.JsfLibraryTask.Config.JsfProject.MyFaces;
import static org.jboss.installer.validators.JsfValidator.JSF_PROJECT_MISMATCHED_KEY;
import static org.jboss.installer.validators.JsfValidator.JSF_PROJECT_NOT_DETECTED_KEY;
import static org.jboss.installer.validators.JsfValidator.JSF_VERSION_NOT_DETECTED_KEY;
import static org.jboss.installer.validators.JsfValidator.JSF_VERSION_NOT_SUPPORTED_KEY;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class JsfValidatorTest {

    @Mock
    private JsfUtils jsfUtils;
    private JsfValidator jsfValidator;
    private LanguageUtils languageUtils = new MockLanguageUtils();
    private JsfLibraryTask.Config config;
    private URL implJarUrl;

    @Before
    public void setUp() throws Exception {
        jsfValidator = new JsfValidator(jsfUtils, languageUtils);

        when(jsfUtils.cleanedVer(any())).thenCallRealMethod().thenCallRealMethod();
        when(jsfUtils.verifyIsImpl(any())).thenAnswer((Answer<Boolean>) inv -> {
            final JarFile jar = inv.getArgument(0);
            return jar.getName().contains("impl");
        });

        config = new JsfLibraryTask.Config();
        config.setJsfProject(Mojarra);
        implJarUrl = JsfValidatorTest.class.getClassLoader().getResource("jars/mojarra-impl.jar");

        config.setImplJarPath(Paths.get(implJarUrl.toURI()).toAbsolutePath().toString());
    }

    @Test
    public void testErrorIfUnableToGetVersionFromSelectedJars() throws Exception {
        config.setJsfProject(Mojarra);

        when(jsfUtils.getVersion(any())).thenReturn(null);
        when(jsfUtils.getProject(any())).thenReturn(Mojarra);

        ValidationResult result = jsfValidator.validate(config);

        assertEquals(result.getMessage(), ValidationResult.Result.WARNING, result.getResult());
        assertEquals(JSF_VERSION_NOT_DETECTED_KEY, result.getMessage());
    }

    @Test
    public void testMojarraDetectedVersionsMatchIgnoresMicro() throws Exception {
        config.setJsfProject(Mojarra);

        when(jsfUtils.getVersion(any())).thenReturn("4.0").thenReturn("4.0.1");
        when(jsfUtils.getProject(any())).thenReturn(Mojarra);

        ValidationResult result = jsfValidator.validate(config);

        assertEquals(result.getMessage(), ValidationResult.Result.OK, result.getResult());
    }

    @Test
    public void testErrorIfUnableToDetectApiProject() throws Exception {
        config.setJsfProject(null);

        when(jsfUtils.getProject(any())).thenReturn(null);

        ValidationResult result = jsfValidator.validate(config);

        assertEquals(ValidationResult.Result.WARNING, result.getResult());
        assertTrue("Wrong error: " + result.getMessage(), result.getMessage().startsWith(JSF_PROJECT_NOT_DETECTED_KEY));
    }

    @Test
    public void testErrorIfUnableToDetectImplProject() throws Exception {
        config.setJsfProject(Mojarra);

        when(jsfUtils.getProject(any())).thenReturn(null);
        when(jsfUtils.getVersion(any())).thenReturn("4.0.1");

        ValidationResult result = jsfValidator.validate(config);

        assertEquals(result.getMessage(), ValidationResult.Result.WARNING, result.getResult());
        assertThat(result.getMessage())
                .startsWith(JSF_PROJECT_NOT_DETECTED_KEY);
    }

    @Test
    public void testErrorIfDetectedImplsDontMatchUsersChoice() throws Exception {
        config.setJsfProject(Mojarra);

        when(jsfUtils.getProject(any())).thenReturn(MyFaces);

        ValidationResult result = jsfValidator.validate(config);

        assertEquals(ValidationResult.Result.ERROR, result.getResult());
        assertTrue("Wrong error: " + result.getMessage(), result.getMessage().startsWith(JSF_PROJECT_MISMATCHED_KEY));
    }

    @Test
    public void testErrorIfDetectedVersionDoesntMatchAllowed() throws Exception {
        config.setJsfProject(Mojarra);

        when(jsfUtils.getProject(any())).thenReturn(Mojarra);
        when(jsfUtils.getVersion(any())).thenReturn("3.0.0");

        ValidationResult result = jsfValidator.validate(config);

        assertEquals(ValidationResult.Result.ERROR, result.getResult());
        assertTrue("Wrong error: " + result.getMessage(), result.getMessage().startsWith(JSF_VERSION_NOT_SUPPORTED_KEY));
    }
}