package org.apache.sling.crankstart.launcher;

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

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.ServerSocket;
import java.util.Random;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.sling.commons.json.JSONArray;
import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.commons.testing.junit.Retry;
import org.apache.sling.commons.testing.junit.RetryRule;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;

/** Verify that we can start the Felix HTTP service
 *  with a {@link CrankstartBootstrap}. 
 */
public class CrankstartBootstrapTest {
    
    private static final int port = getAvailablePort();
    private static DefaultHttpClient client;
    private static Thread crankstartThread;
    private static String baseUrl = "http://localhost:" + port;
    public static final String TEST_RESOURCE = "/launcher-test.crank.txt";
    public static final String TEST_SYSTEM_PROPERTY = "the.test.system.property";
            
    @Rule
    public final RetryRule retryRule = new RetryRule();
    
    private static int getAvailablePort() {
        int result = -1;
        ServerSocket s = null;
        try {
            try {
                s = new ServerSocket(0);
                result = s.getLocalPort();
            } finally {
                if(s != null) {
                    s.close();
                }
            }
        } catch(Exception e) {
            throw new RuntimeException("getAvailablePort failed", e);
        }
        return result;
    }
    
    @Before
    public void setupHttpClient() {
        client = new DefaultHttpClient(); 
    }
    
    private void setAdminCredentials() {
        client.getCredentialsProvider().setCredentials(
                AuthScope.ANY, 
                new UsernamePasswordCredentials("admin", "admin"));
        client.addRequestInterceptor(new PreemptiveAuthInterceptor(), 0);
    }
    
    @BeforeClass
    public static void testExtensionPropertyBeforeTests() {
        assertNull(TEST_SYSTEM_PROPERTY + " should not be set before tests", System.getProperty(TEST_SYSTEM_PROPERTY));
    }
    
    @BeforeClass
    public static void setup() {
        client = new DefaultHttpClient(); 
        final HttpUriRequest get = new HttpGet(baseUrl);
        System.setProperty("http.port", String.valueOf(port));
        System.setProperty("osgi.storage.path", getOsgiStoragePath());
        
        final InputStream is = CrankstartBootstrapTest.class.getResourceAsStream(TEST_RESOURCE);
        assertNotNull("Expecting test resource to be found:" + TEST_RESOURCE, is);
        final Reader input = new InputStreamReader(is);
        
        try {
            client.execute(get);
            fail("Expecting connection to " + port + " to fail before starting HTTP service");
        } catch(IOException expected) {
        }
        
        crankstartThread = new Thread() {
            public void run() {
                try {
                    new CrankstartBootstrap(input).start();
                } catch(Exception e) {
                    e.printStackTrace();
                    fail("CrankstartBootstrap exception:" + e);
                } finally {
                    try {
                        input.close();
                    } catch(IOException ignoreTheresNotMuchWeCanDoAnyway) {
                    }
                }
            }
        };
        crankstartThread.setDaemon(true);
        crankstartThread.start();
    }
    
    @AfterClass
    public static void cleanup() throws InterruptedException {
        crankstartThread.interrupt();
        crankstartThread.join();
    }
    
    private void closeConnection(HttpResponse r) throws IOException {
        if(r != null && r.getEntity() != null) {
            EntityUtils.consume(r.getEntity());
        }
    }
    
    @Test
    @Retry(timeoutMsec=10000, intervalMsec=250)
    public void testHttpRoot() throws Exception {
        final HttpUriRequest get = new HttpGet(baseUrl);
        HttpResponse response = null;
        try {
            response = client.execute(get);
            assertEquals("Expecting page not found at " + get.getURI(), 404, response.getStatusLine().getStatusCode());
        } finally {
            closeConnection(response);
        }
    }
    
    @Test
    @Retry(timeoutMsec=10000, intervalMsec=250)
    public void testSingleConfigServlet() throws Exception {
        final HttpUriRequest get = new HttpGet(baseUrl + "/single");
        HttpResponse response = null;
        try {
            response = client.execute(get);
            assertEquals("Expecting success for " + get.getURI(), 200, response.getStatusLine().getStatusCode());
        } finally {
            closeConnection(response);
        }
    }
    
    @Test
    @Retry(timeoutMsec=10000, intervalMsec=250)
    public void testConfigFactoryServlet() throws Exception {
        final String [] paths = { "/foo", "/bar/test" };
        for(String path : paths) {
            final HttpUriRequest get = new HttpGet(baseUrl + path);
            HttpResponse response = null;
            try {
                response = client.execute(get);
                assertEquals("Expecting success for " + get.getURI(), 200, response.getStatusLine().getStatusCode());
            } finally {
                closeConnection(response);
            }
        }
    }
    
    @Test
    public void testExtensionCommand() {
        // The SystemPropertyCommand, provided by our test-services bundle, should have
        // processed the test.system.property instruction in our launcher file 
        assertEquals("was set by test-services bundle", System.getProperty(TEST_SYSTEM_PROPERTY));
    }
    
    @Test
    @Retry(timeoutMsec=10000, intervalMsec=250)
    public void testJUnitServlet() throws Exception {
        final String path = "/system/sling/junit";
        final HttpUriRequest get = new HttpGet(baseUrl + path);
        HttpResponse response = null;
        try {
            response = client.execute(get);
            assertEquals("Expecting JUnit servlet to be installed via sling extension command, at " + get.getURI(), 200, response.getStatusLine().getStatusCode());
        } finally {
            closeConnection(response);
        }
    }
    
    @Test
    @Retry(timeoutMsec=10000, intervalMsec=250)
    public void testAdditionalBundles() throws Exception {
        setAdminCredentials();
        final String basePath = "/system/console/bundles/";
        final String [] addBundles = {
                "org.apache.sling.commons.mime",
                "org.apache.sling.settings"
        };
        
        for(String name : addBundles) {
            final String path = basePath + name;
            final HttpUriRequest get = new HttpGet(baseUrl + path);
            HttpResponse response = null;
            try {
                response = client.execute(get);
                assertEquals("Expecting additional bundle to be present at " + get.getURI(), 200, response.getStatusLine().getStatusCode());
            } finally {
                closeConnection(response);
            }
        }
    }
    
    @Test
    @Retry(timeoutMsec=10000, intervalMsec=250)
    public void testFelixFormatConfig() throws Exception {
        setAdminCredentials();
        final String path = "/system/console/config/configuration-status-20140606-1347+0200.txt";
        final HttpUriRequest get = new HttpGet(baseUrl + path);
        HttpResponse response = null;
        try {
            response = client.execute(get);
            assertEquals("Expecting config dump to be available at " + get.getURI(), 200, response.getStatusLine().getStatusCode());
            assertNotNull("Expecting response entity", response.getEntity());
            String encoding = "UTF-8";
            if(response.getEntity().getContentEncoding() != null) {
                encoding = response.getEntity().getContentEncoding().getValue();
            }
            final String content = IOUtils.toString(response.getEntity().getContent(), encoding);
            final String [] expected = new String[] {
                    "array = [foo, bar.from.launcher.test]",
                    "service.ranking.launcher.test = 54321"
            };
            for(String exp : expected) {
                assertTrue("Expecting config content to contain " + exp, content.contains(exp));
            }
        } finally {
            closeConnection(response);
        }
    }
    
    @Test
    @Retry(timeoutMsec=10000, intervalMsec=250)
    public void testSpecificStartLevel() throws Exception {
        // Verify that this bundle is only installed, as it's set to start level 99
        setAdminCredentials();
        final String path = "/system/console/bundles/org.apache.commons.collections.json";
        final HttpUriRequest get = new HttpGet(baseUrl + path);
        HttpResponse response = null;
        try {
            response = client.execute(get);
            assertEquals("Expecting bundle status to be available at " + get.getURI(), 200, response.getStatusLine().getStatusCode());
            assertNotNull("Expecting response entity", response.getEntity());
            String encoding = "UTF-8";
            if(response.getEntity().getContentEncoding() != null) {
                encoding = response.getEntity().getContentEncoding().getValue();
            }
            final String content = IOUtils.toString(response.getEntity().getContent(), encoding);
            
            // Start level is in the props array, with key="Start Level"
            final JSONObject status = new JSONObject(content);
            final JSONArray props = status.getJSONArray("data").getJSONObject(0).getJSONArray("props");
            final String KEY = "key";
            final String SL = "Start Level";
            boolean found = false;
            for(int i=0; i < props.length(); i++) {
                final JSONObject o = props.getJSONObject(i);
                if(o.has(KEY) && SL.equals(o.getString(KEY))) {
                    found = true;
                    assertEquals("Expecting the start level that we set", "99", o.getString("value"));
                }
            }
            assertTrue("Expecting start level to be found in JSON output", found);
        } finally {
            closeConnection(response);
        }
    }
    
    private static String getOsgiStoragePath() {
        final File tmpRoot = new File(System.getProperty("java.io.tmpdir"));
        final Random random = new Random();
        final File tmpFolder = new File(tmpRoot, System.currentTimeMillis() + "_" + random.nextInt());
        if(!tmpFolder.mkdir()) {
            fail("Failed to create " + tmpFolder.getAbsolutePath());
        }
        tmpFolder.deleteOnExit();
        return tmpFolder.getAbsolutePath();
    }
}