package de.renew.plugin.command;

import java.util.List;

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

import static de.renew.plugin.command.CommandHelper.assertString;
import static de.renew.plugin.command.CommandHelper.doExecuteSuccessfully;
import static de.renew.plugin.command.CommandHelper.doExecuteUnsuccessfully;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class ScriptCommandTest {
    public static final String FILE_PREFIX = "src/test/resources/de.renew.plugin.command/";
    private ScriptCommand _cmd;

    @BeforeEach
    public void prepare() {
        _cmd = new ScriptCommand();
    }

    @Test
    public void testSplitStringNoQuotes() {
        List<String> result = _cmd.splitString("this is a sample");
        assertEquals(4, result.size());
        assertEquals("this", result.get(0));
        assertEquals("is", result.get(1));
        assertEquals("a", result.get(2));
        assertEquals("sample", result.get(3));
    }

    @Test
    public void testSplitStringWithQuotes() {
        List<String> result = _cmd.splitString("this is \"a sample\"");
        assertEquals(3, result.size(), "Result is " + result);
        assertEquals("this", result.get(0));
        assertEquals("is", result.get(1));
        assertEquals("a sample", result.get(2));
    }

    @Test
    public void testSplitStringMixed() {
        List<String> result = _cmd.splitString("this is \"a sample\" test");
        assertEquals(4, result.size(), "Result is " + result);
        assertEquals("this", result.get(0));
        assertEquals("is", result.get(1));
        assertEquals("a sample", result.get(2));
        assertEquals("test", result.get(3));
    }

    @Test
    public void testGetArguments() {
        assertEquals("fileNames", _cmd.getArguments());
    }

    @Test
    public void testGetDescription() {
        assertEquals(String.class, _cmd.getDescription().getClass());
    }

    @Test
    public void testExecuteWithNoAppropriateFile() {
        // This is not good practice to rely on a semi random string in the output.
        final String output = doExecuteSuccessfully(new ScriptCommand(), "gibberish");
        assertString(
            "ScriptCommand: Try to load file gibberish"
                + "ScriptCommand: file gibberish not found.",
            output);
    }

    @Test
    public void testExecuteToManyArguments() {
        // This is not good practice to rely on a semi random string in the output.
        final String output = doExecuteSuccessfully(new ScriptCommand(), "gibberish", "secondArg");
        assertString(
            "ScriptCommand: more than one parameter given: using only gibberish"
                + "ScriptCommand: Try to load file gibberish"
                + "ScriptCommand: file gibberish not found.",
            output);
    }

    @Test
    public void testExecuteNoArguments() {
        final String[] args1 = new String[1];
        final String[] args2 = new String[2];
        //noinspection DataFlowIssue
        assertThrows(NullPointerException.class, () -> _cmd.execute(null, null));

        final CommandHelper.Result result =
            doExecuteUnsuccessfully(new ScriptCommand(), NullPointerException.class, args1);
        assertString("ScriptCommand: Try to load file null", result.output());

        final CommandHelper.Result result2 =
            doExecuteUnsuccessfully(new ScriptCommand(), NullPointerException.class, args2);
        assertString(
            "ScriptCommand: more than one parameter given: using only nullScriptCommand: Try to load file null",
            result2.output());

        final CommandHelper.Result result3 = doExecuteUnsuccessfully(
            new ScriptCommand(), NullPointerException.class, (String[]) null);
        assertString("", result3.output());
    }

    @Test
    public void testExecuteWithFile() {
        // TODO: The following is not good practice to rely on some semi random strings to be returned.
        //  An Enhancement would be to add (only in the test env) a command to the list in PluginManager which is controlled by the test / e.g. a Mock
        final String output = doExecuteSuccessfully(
            new ScriptCommand(), FILE_PREFIX + "ScriptCommandExecuteTest.txt");
        assertString(
            "ScriptCommand: Try to load file src/test/resources/de.renew.plugin.command/ScriptCommandExecuteTest.txt"
                + "ScriptCommand: unknown command: gibberish" + "Please use list command instead!",
            output);
    }



}