package fi.helsinki.cs.tmc.cli.updater;

import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;

import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.containsString;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import fi.helsinki.cs.tmc.cli.io.TestIo;

import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import java.io.File;
import java.io.InputStream;
import java.io.IOException;

public class TmcCliUpdaterTest {

    static String latestJson;
    static String apiLimitExeededJson;

    TestIo io;

    @BeforeClass
    public static void setUpClass() throws IOException {
        latestJson = readResource("latest.json");
        assertNotNull(latestJson);

        apiLimitExeededJson = readResource("api_rate_limit_exeeded.json");
        assertNotNull(apiLimitExeededJson);
    }

    @Before
    public void setUp() {
        io = new TestIo();
    }

    @After
    public void tearDown() {
    }

    @Test
    public void stub() {
        assertTrue(true);
    }

    @Test
    public void doNothingIfReleaseEqualsCurrentVersion() {
        TmcCliUpdater updater = spy(new TmcCliUpdater(io, "0.1.1", false));
        when(updater.fetchLatestReleaseJson()).thenReturn(latestJson);
        updater.run();
        verify(updater, never()).fetchTmcCliBinary(any(String.class), any(File.class));
        assertTrue(io.out().isEmpty());
    }

    @Test
    public void doNothingIfFetchingReleaseJsonFails() {
        TmcCliUpdater updater = spy(new TmcCliUpdater(io, "0.1.0", false));
        when(updater.fetchLatestReleaseJson()).thenReturn(null);
        updater.run();
        verify(updater, never()).fetchTmcCliBinary(any(String.class), any(File.class));
        assertTrue(io.out().isEmpty());
    }

    @Test
    public void doNothingIfFetchedJsonIsApiRateLimitExceeded() {
        TmcCliUpdater updater = spy(new TmcCliUpdater(io, "0.1.0", false));
        when(updater.fetchLatestReleaseJson()).thenReturn(apiLimitExeededJson);
        updater.run();
        verify(updater, never()).fetchTmcCliBinary(any(String.class), any(File.class));
        assertTrue(io.out().isEmpty());
    }

    @Test
    public void doNothingIfUserDoesntWantToUpdate() {
        io.addLinePrompt("n");
        TmcCliUpdater updater = spy(new TmcCliUpdater(io, "0.1.0", false));
        when(updater.fetchLatestReleaseJson()).thenReturn(latestJson);
        updater.run();
        assertThat(io.out(), containsString("A new version of tmc-cli is available!"));
        verify(updater, never()).fetchTmcCliBinary(any(String.class), any(File.class));
    }

    // Expected to fail once autoupdater is properly implemented on Windows.
    @Test
    public void newReleaseShowsDownloadLinkOnWindows() {
        TmcCliUpdater updater = spy(new TmcCliUpdater(io, "0.1.0", true));
        when(updater.fetchLatestReleaseJson()).thenReturn(latestJson);
        updater.run();
        assertThat(io.out(), containsString("A new version of tmc-cli is available!"));
        assertThat(io.out(), containsString("Download: https://"));
        verify(updater, never()).fetchTmcCliBinary(any(String.class), any(File.class));
    }

    private static String readResource(String resourceName) throws IOException {
        InputStream inputStream = TmcCliUpdaterTest.class.getClassLoader()
                .getResourceAsStream(resourceName);
        if (inputStream == null) {
            return null;
        }
        String resourceContent = IOUtils.toString(inputStream, "UTF-8");
        IOUtils.closeQuietly(inputStream);
        return resourceContent;
    }
}

@@ -282,16 +282,61 @@
 rs.any;%0A
+import static org.mockito.Mockito.doNothing;%0A
 import s
@@ -407,16 +407,57 @@
 to.spy;%0A
+import static org.mockito.Mockito.times;%0A
 import s
@@ -2957,24 +2957,770 @@
 s));%0A    %7D%0A%0A
+    @Test%0A    public void downloadsAndRunsNewBinaryIfOk() %7B%0A        io.addLinePrompt(%22yes%22);%0A        TmcCliUpdater updater = spy(new TmcCliUpdater(io, %220.1.0%22, false));%0A        when(updater.fetchLatestReleaseJson()).thenReturn(latestJson);%0A        doNothing().when(updater).fetchTmcCliBinary(any(String.class), any(File.class));%0A        doNothing().when(updater).runNewTmcCliBinary(any(String.class));%0A        updater.run();%0A        assertThat(io.out(), containsString(%22A new version of tmc-cli is available!%22));%0A        assertThat(io.out(), containsString(%22Downloading...%22));%0A        verify(updater, times(1)).fetchTmcCliBinary(any(String.class), any(File.class));%0A        verify(updater, times(1)).runNewTmcCliBinary(any(String.class));%0A    %7D%0A%0A
     // Expec

Add test