package fi.helsinki.cs.tmc.cli;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;

import fi.helsinki.cs.tmc.cli.core.CliContext;
import fi.helsinki.cs.tmc.cli.io.Io;
import fi.helsinki.cs.tmc.cli.io.TestIo;
import fi.helsinki.cs.tmc.cli.updater.AutoUpdater;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import java.util.HashMap;

@RunWith(PowerMockRunner.class)
@PrepareForTest(AutoUpdater.class)
public class ApplicationTest {

    private Application app;
    private TestIo io;

    @Before
    public void setUp() {
        io = new TestIo();
        app = new Application(new CliContext(io));
        mockStatic(AutoUpdater.class);
    }

    @Test
    public void versionWorksWithRightParameter() {
        String[] args = {"-v", "foo"};
        app.run(args);
        io.assertContains("TMC-CLI version");
        io.assertNotContains("Command foo doesn't exist.");
    }

    @Test
    public void failWhenInvalidOption() {
        String[] args = {"-a34t3"};
        app.run(args);
        io.assertContains("Unrecognized option");
    }

    @Test
    public void helpWorksWithRightParameter() {
        String[] args = {"-h"};
        app.run(args);
        io.assertContains("Usage: tmc");
    }

    @Test
    public void helpOfHelpCommandIsNotGiven() {
        String[] args = {"-h", "help"};
        app.run(args);
        io.assertContains("help");
        io.assertNotContains("Usage: tmc help");
    }

    @Test
    public void runCommandWorksWithWrongParameter() {
        String[] args = {"foo"};
        app.run(args);
        io.assertContains("Command foo doesn't exist");
    }

    @Test
    public void runAutoUpdate() {
        String[] args = {"help"};
        AutoUpdater mockUpdater = mock(AutoUpdater.class);
        when(AutoUpdater.createUpdater(any(Io.class), anyString(), any(Boolean.class)))
                .thenReturn(mockUpdater);
        when(mockUpdater.run()).thenReturn(true);

        CliContext ctx = spy(new CliContext(null));
        when(ctx.getProperties()).thenReturn(new HashMap<String, String>());

        app = new Application(ctx);
        app.run(args);

        verifyStatic(times(1));
        AutoUpdater.createUpdater(any(Io.class), anyString(), any(Boolean.class));
    }

    @Test
    public void runWithForceUpdate() {
        String[] args = {"--force-update", "foo"};
        app = spy(app);
        doReturn(true).when(app).runAutoUpdate();
        app.run(args);
        io.assertNotContains("Command foo doesn't exist.");
        verify(app, times(1)).runAutoUpdate();
    }
}

@@ -1764,24 +1764,519 @@
 age: tmc%22);%0A
+        io.assertContains(%22--help-all%22);%0A        io.assertContains(%22--help%22);%0A    %7D%0A%0A    @Test%0A    public void helpDoesntHaveHiddenCommands() %7B%0A        String%5B%5D args = %7B%22-h%22%7D;%0A        app.run(args);%0A        io.assertContains(%22Usage: tmc%22);%0A        io.assertNotContains(%22shell-helper%22);%0A    %7D%0A%0A    @Test%0A    public void helpAllHasHiddenCommands() %7B%0A        String%5B%5D args = %7B%22--help-all%22%7D;%0A        app.run(args);%0A        io.assertContains(%22Usage: tmc%22);%0A        io.assertContains(%22shell-helper%22);%0A
     %7D%0A%0A    @
@@ -2418,20 +2418,26 @@
 ntains(%22
-help
+Usage: tmc
 %22);%0A    
@@ -2480,32 +2480,574 @@
  help%22);%0A    %7D%0A%0A
+    @Test%0A    public void listOfEveryCommand() %7B%0A        String%5B%5D args = %7B%22--help-all%22%7D;%0A        app.run(args);%0A        io.assertContains(%22TMC commands in all%22);%0A    %7D%0A%0A    @Test%0A    public void helpOptionForAdminCommands() %7B%0A        String%5B%5D args = %7B%22--help-admin%22%7D;%0A        app.run(args);%0A        io.assertContains(%22TMC commands in admin%22);%0A    %7D%0A%0A    @Test%0A    public void helpOptionForHiddenCommandsDoesntExist() %7B%0A        String%5B%5D args = %7B%22--help-hidden%22%7D;%0A        app.run(args);%0A        io.assertContains(%22Unrecognized option%22);%0A    %7D%0A%0A
     @Test%0A    pu

Add more unit tests for help options.