// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.config.server.deploy;

import com.google.common.io.Files;
import com.yahoo.cloud.config.ConfigserverConfig;
import com.yahoo.config.model.api.ModelFactory;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Version;
import com.yahoo.test.ManualClock;
import org.junit.Ignore;
import org.junit.Test;

import java.io.IOException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

/**
 * @author bratseth
 */
public class HostedDeployTest {
    private static final String dockerRegistry = "foo.com:4443";
    private static final String dockerVespaBaseImage = "/vespa/ci";
    private static final ConfigserverConfig config = new ConfigserverConfig(new ConfigserverConfig.Builder()
                                                                                    .configServerDBDir(Files.createTempDir()
                                                                                                            .getAbsolutePath())
                                                                                    .dockerRegistry(dockerRegistry)
                                                                                    .dockerVespaBaseImage(dockerVespaBaseImage)
                                                                                    .configServerDBDir(Files.createTempDir()
                                                                                                            .getAbsolutePath())
                                                                                    .hostedVespa(true)
                                                                                    .multitenant(true));

    @Test
    public void testRedeploy() throws InterruptedException, IOException {
        DeployTester tester = new DeployTester("src/test/apps/hosted/", config);
        tester.deployApp("myApp");

        Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive();                
        assertTrue(deployment.isPresent());
        deployment.get().prepare();
        deployment.get().activate();
    }

    @Test
    public void testRedeployAfterExpiredValidationOverride() throws InterruptedException, IOException {
        // Old version of model fails, but application disables loading old models until 2016-10-10, so deployment works
        ManualClock clock = new ManualClock("2016-10-09T00:00:00");
        List<ModelFactory> modelFactories = new ArrayList<>();
        modelFactories.add(DeployTester.createDefaultModelFactory(clock));
        modelFactories.add(DeployTester.createFailingModelFactory(Version.fromIntValues(1, 0, 0))); // older than default
        DeployTester tester = new DeployTester("src/test/apps/validationOverride/", modelFactories, config);
        tester.deployApp("myApp");

        // Redeployment from local active works
        {
            Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive();
            assertTrue(deployment.isPresent());
            deployment.get().prepare();
            deployment.get().activate();
        }

        clock.advance(Duration.ofDays(2)); // validation override expires

        // Redeployment from local active also works after the validation override expires
        {
            Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive();
            assertTrue(deployment.isPresent());
            deployment.get().prepare();
            deployment.get().activate();
        }
        
        // However, redeployment from the outside fails after this date
        {
            try {
                tester.deployApp("myApp");
                fail("Expected redeployment to fail");
            }
            catch (Exception expected) {
                // success
            }
        }
    }

    @Test
    @Ignore //WIP
    public void testDeployWithDockerImage() throws InterruptedException, IOException {
        final String vespaVersion = "6.51.1";
        DeployTester tester = new DeployTester("src/test/apps/hosted/", config);
        ApplicationId applicationId = tester.deployApp("myApp", Optional.of(vespaVersion));
        assertProvisionInfo(vespaVersion, tester, applicationId);

        System.out.println("Redeploy");
        Optional<com.yahoo.config.provision.Deployment> deployment = tester.redeployFromLocalActive();
        assertTrue(deployment.isPresent());
        deployment.get().prepare();
        deployment.get().activate();
        //assertProvisionInfo(vespaVersion, tester, applicationId);
    }

    private void assertProvisionInfo(String vespaVersion, DeployTester tester, ApplicationId applicationId) {
        tester.getProvisionInfoFromDeployedApp(applicationId).getHosts().stream()
              .forEach(h -> assertEquals(dockerRegistry + dockerVespaBaseImage + ":" + vespaVersion,
                                         h.membership().get().cluster().dockerImage().get()));
    }

}

@@ -919,1075 +919,8 @@
 ci%22;
-%0A    private static final ConfigserverConfig config = new ConfigserverConfig(new ConfigserverConfig.Builder()%0A                                                                                    .configServerDBDir(Files.createTempDir()%0A                                                                                                            .getAbsolutePath())%0A                                                                                    .dockerRegistry(dockerRegistry)%0A                                                                                    .dockerVespaBaseImage(dockerVespaBaseImage)%0A                                                                                    .configServerDBDir(Files.createTempDir()%0A                                                                                                            .getAbsolutePath())%0A                                                                                    .hostedVespa(true)%0A                                                                                    .multitenant(true));
 %0A%0A  
@@ -1066,37 +1066,57 @@
 apps/hosted/%22, c
-onfig
+reateConfigserverConfig()
 );%0A        teste
@@ -1240,32 +1240,16 @@
 ctive();
-                
 %0A       
@@ -2029,21 +2029,41 @@
 ories, c
-onfig
+reateConfigserverConfig()
 );%0A     
@@ -2820,24 +2820,16 @@
       %7D%0A
-        
 %0A       
@@ -3366,21 +3366,41 @@
 ted/%22, c
-onfig
+reateConfigserverConfig()
 );%0A     
@@ -4283,10 +4283,632 @@
 %0A    %7D%0A%0A
+    private static ConfigserverConfig createConfigserverConfig() %7B%0A        return new ConfigserverConfig(new ConfigserverConfig.Builder()%0A                                              .configServerDBDir(Files.createTempDir()%0A                                                                      .getAbsolutePath())%0A                                              .dockerRegistry(dockerRegistry)%0A                                              .dockerVespaBaseImage(dockerVespaBaseImage)%0A                                              .hostedVespa(true)%0A                                              .multitenant(true));%0A    %7D%0A%0A
 %7D%0A

Make sure we create new config (with temp dir) for every test