/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sling.testing.teleporter.client;

import static org.junit.Assert.fail;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonException;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonString;
import javax.json.JsonValue;
import javax.json.JsonValue.ValueType;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runners.model.MultipleFailureException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Barebones HTTP client that supports just what the teleporter needs, with no
 * dependencies outside of java.* and org.junit. Prevents us from imposing a
 * particular HTTP client version.
 */
class TeleporterHttpClient {
    private final Logger log = LoggerFactory.getLogger(getClass());

    private final String CHARSET = "UTF-8";
    private final String baseUrl;
    private String credentials = null;
    private final String testServletPath;
    private final int httpTimeoutSeconds;

    static final class SimpleHttpResponse {
        private final int status;
        private final String body;

        public SimpleHttpResponse(int status, String body) {
            super();
            this.status = status;
            this.body = body;
        }

        public int getStatus() {
            return status;
        }

        public String getBody() {
            return body;
        }
    }

    TeleporterHttpClient(String baseUrl, String testServletPath) {
        this(baseUrl, testServletPath, ClientSideTeleporter.DEFAULT_TEST_READY_TIMEOUT_SECONDS);
    }

    TeleporterHttpClient(String baseUrl, String testServletPath, int httpTimeoutSeconds) {
        this.baseUrl = baseUrl;
        this.httpTimeoutSeconds = httpTimeoutSeconds;
        if(!testServletPath.endsWith("/")) {
            testServletPath += "/";
        }
        this.testServletPath = testServletPath;
    }

    void setCredentials(String cred) {
        credentials = cred;
    }

    int getHttpTimeoutSeconds() {
        return httpTimeoutSeconds;
    }

    static String encodeBase64(String data) {
        try {
            return Base64.encodeBase64String(data.getBytes("UTF-8"));
        } catch(UnsupportedEncodingException uee) {
            throw new RuntimeException(uee);
        }
    }
    
    public void setConnectionCredentials(URLConnection c) {
        if(credentials != null && !credentials.isEmpty()) {
            final String basicAuth = "Basic " + encodeBase64(credentials);
            c.setRequestProperty ("Authorization", basicAuth);
            log.debug("Credentials set");
        }
    }

    /** Wait until specified URL returns specified status */
    public String waitForStatus(String url, int expectedStatus, int timeoutMsec) throws IOException {
        log.debug("Waiting for status {} at {}, timeout {} msec", expectedStatus, url, timeoutMsec);
        final long end = System.currentTimeMillis() + timeoutMsec;
        final Set<Integer> statusSet = new HashSet<Integer>();
        final ExponentialBackoffDelay d = new ExponentialBackoffDelay(50,  250);
        while(System.currentTimeMillis() < end) {
            try {
                final SimpleHttpResponse response = getHttpGetStatus(url);
                statusSet.add(response.getStatus());
                if(response.getStatus() == expectedStatus) {
                    return response.getBody();
                }
                d.waitNextDelay();
            } catch(Exception ignore) {
            }
        }
        throw new IOException("Did not get status " + expectedStatus + " at " + url + " after " + timeoutMsec + " msec, got " + statusSet);
    }

    HttpURLConnection setHttpTimeouts(HttpURLConnection c) {
        final int timeoutMsec = httpTimeoutSeconds * 1000;
        c.setConnectTimeout(timeoutMsec);
        c.setReadTimeout(timeoutMsec);
        log.debug("HTTP connect + read timeouts set to {} msec", timeoutMsec);
        return c;
    }
    
    void installBundle(InputStream bundle, String bundleSymbolicName, int webConsoleReadyTimeoutSeconds) throws MalformedURLException, IOException {
        // Equivalent of
        // curl -u admin:admin -F action=install -Fbundlestart=1 -Fbundlefile=@somefile.jar http://localhost:8080/system/console/bundles
        final String url = baseUrl + "/system/console/bundles";
        final String contentType = "application/octet-stream";
        final HttpURLConnection c = setHttpTimeouts((HttpURLConnection)new URL(url).openConnection());
        
        waitForStatus(url, 200, webConsoleReadyTimeoutSeconds * 1000);
        
        try {
            setConnectionCredentials(c);
            new MultipartAdapter(c, CHARSET)
            .parameter("action", "install")
            .parameter("bundlestart", "1")
            .file("bundlefile", bundleSymbolicName + ".jar", contentType, bundle)
            .close();
            final int status = c.getResponseCode();
            if(status != 302) {
                throw new IOException("Got status code " + status + " for " + url);
            }
            log.debug("POST request to install bundle {} successful", bundleSymbolicName);
        } finally {
            cleanup(c);
        }
    }
    
    void verifyCorrectBundleState(String bundleSymbolicName, int timeoutInSeconds) throws IOException {
        log.debug("Verifying bundle {} state, timeout {} seconds", bundleSymbolicName, timeoutInSeconds);
        final String url = baseUrl + "/system/console/bundles/" + bundleSymbolicName + ".json";
        
        final long end = System.currentTimeMillis() + timeoutInSeconds * 1000;
        final ExponentialBackoffDelay d = new ExponentialBackoffDelay(50,  250);
        while(System.currentTimeMillis() < end) {
            
            String jsonBody = waitForStatus(url, 200, timeoutInSeconds * 1000);
            // deserialize json (https://issues.apache.org/jira/browse/SLING-6536)
            try (JsonReader jsonReader = Json.createReader(new StringReader(jsonBody))) {
                // extract state
                JsonArray jsonArray = jsonReader.readObject().getJsonArray("data");
                if (jsonArray == null) {
                    throw new JsonException("Could not find 'data' array");
                }
                JsonObject bundleObject = jsonArray.getJsonObject(0);
                String state = bundleObject.getString("state");
                if ("Active".equals(state)) {
                    log.debug("Bundle {} is active", bundleSymbolicName);
                    return;
                }
                // otherwise evaluate the import section
                JsonArray propsArray = bundleObject.getJsonArray("props");
                if (propsArray == null) {
                    throw new JsonException("Could not find 'props' object");
                }
                // iterate through all of them until key="Imported Packages" is found
                for (JsonValue propValue : propsArray) {
                    if (propValue.getValueType().equals(ValueType.OBJECT)) {
                        JsonObject propObject = (JsonObject)propValue;
                        if ("Imported Packages".equals(propObject.getString("key"))) {
                            JsonArray importedPackagesArray = propObject.getJsonArray("value");
                            String reason = null;
                            for (JsonValue importedPackageValue : importedPackagesArray) {
                                if (importedPackageValue.getValueType().equals(ValueType.STRING)) {
                                    String importedPackage = ((JsonString)importedPackageValue).getString();
                                    if (importedPackage.startsWith("ERROR:")) {
                                        reason = importedPackage;
                                    }
                                }
                            }
                            // only if ERROR is found there is no more need to wait for the bundle to become active, otherwise it might just be started in the background
                            if (reason != null) {
                                throw new IllegalStateException("The test bundle '" + bundleSymbolicName + "' is in state '" + state +"'. This is due to unresolved import-packages: " + reason);
                            }
                        }
                    }
                }
            } catch (JsonException|IndexOutOfBoundsException e) {
                throw new IllegalArgumentException("Test bundle '" + bundleSymbolicName +"' not correctly installed. Could not parse JSON response though to expose further information: " + jsonBody, e);
            }
            d.waitNextDelay();
        }
        throw new IOException("Bundle '" + bundleSymbolicName + "' was not started after " + timeoutInSeconds + " seconds. The check at " + url + " was not successfull. Probably some dependent bundle was not started.");
    }

    void uninstallBundle(String bundleSymbolicName, int webConsoleReadyTimeoutSeconds) throws MalformedURLException, IOException {
        log.debug("Uninstalling bundle {}", bundleSymbolicName);

        // equivalent of
        // curl -u admin:admin -F action=uninstall http://localhost:8080/system/console/bundles/$N
        final String url = baseUrl + "/system/console/bundles/" + bundleSymbolicName;
        final HttpURLConnection c = setHttpTimeouts((HttpURLConnection)new URL(url).openConnection());
        
        waitForStatus(url, 200, webConsoleReadyTimeoutSeconds * 1000);
        
        try {
            setConnectionCredentials(c);
            new MultipartAdapter(c, CHARSET)
            .parameter("action", "uninstall")
            .close();
            final int status = c.getResponseCode();
            if(status != 200) {
                throw new IOException("Got status code " + status + " for " + url);
            }
            log.debug("POST request to uninstall bundle {} successful", bundleSymbolicName);
        } finally {
            cleanup(c);
        }
    }
    
    public SimpleHttpResponse getHttpGetStatus(String url) throws MalformedURLException, IOException {
        log.debug("getHttpGetStatus: {}", url);
        final HttpURLConnection c = setHttpTimeouts((HttpURLConnection)new URL(url).openConnection());
        setConnectionCredentials(c);
        c.setUseCaches(false);
        c.setDoOutput(true);
        c.setDoInput(true);
        c.setInstanceFollowRedirects(false);
        boolean gotStatus = false;
        int status = 0;
        try {
            status = c.getResponseCode();
            gotStatus = true;
            //4xx: client error, 5xx: server error. See: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html.
            boolean isError = status >= 400;
            //In HTTP error cases, HttpURLConnection only gives you the input stream via #getErrorStream().
            InputStream is = isError ? c.getErrorStream() : c.getInputStream();
            StringWriter writer = new StringWriter();
            IOUtils.copy(is, writer, StandardCharsets.UTF_8);
            log.debug("Got response {} for {}", status, url);
            return new SimpleHttpResponse(status, writer.toString());
        } finally {
            // If we didn't get a status, do not attempt
            // to get input streams as this would retry connecting
            cleanup(c, gotStatus);
        }
    }

    void runTests(String testSelectionPath, int testReadyTimeoutSeconds) throws MalformedURLException, IOException, MultipleFailureException {
        final String testUrl = baseUrl + "/" + testServletPath + testSelectionPath + ".junit_result";
        log.debug("Running tests: {}", testUrl);
        
        // Wait for non-404 response that signals that test bundle is ready
        final long timeout = System.currentTimeMillis() + (testReadyTimeoutSeconds * 1000L);
        final ExponentialBackoffDelay delay = new ExponentialBackoffDelay(25, 1000);
        while(true) {
            if(getHttpGetStatus(testUrl).getStatus() == 200) {
                break;
            }
            if(System.currentTimeMillis() > timeout) {
                fail("Timeout waiting for test at " + testUrl + " (" + testReadyTimeoutSeconds + " seconds)");
                break;
            }
            delay.waitNextDelay();
        }
        
        final HttpURLConnection c = setHttpTimeouts((HttpURLConnection)new URL(testUrl).openConnection());
        try {
        	setConnectionCredentials(c);
            c.setRequestMethod("POST");
            c.setUseCaches(false);
            c.setDoOutput(true);
            c.setDoInput(true);
            c.setInstanceFollowRedirects(false);
            final int status = c.getResponseCode();
            if(status != 200) {
                throw new IOException("Got status code " + status + " for " + testUrl);
            }
        
            final Result result = (Result)new ObjectInputStream(c.getInputStream()).readObject();
            if(result.getFailureCount() > 0) {
                final List<Throwable> failures = new ArrayList<Throwable>(result.getFailureCount());
                for (Failure f : result.getFailures()) {
                    failures.add(f.getException());
                }
                throw new MultipleFailureException(failures);
            }
            log.debug("POST request to run tests successful at {}", testUrl);
        } catch(ClassNotFoundException e) {
            throw new IOException("Exception reading test results:" + e, e);
        } finally {
            cleanup(c);
        }
    }
    
    private void consumeAndClose(InputStream is) throws IOException {
        if(is == null) {
            return;
        }
        final byte [] buffer = new byte[16384];
        while(is.read(buffer) != -1) {
            // nothing to do, just consume the stream
        }
        is.close();
    }
    
    private void cleanup(HttpURLConnection c) {
        cleanup(c, true);
    }
    
    private void cleanup(HttpURLConnection c, boolean includeInputStreams) {
        if(includeInputStreams) {
            try {
                consumeAndClose(c.getInputStream());
            } catch(IOException ignored) {
            }
            try {
                consumeAndClose(c.getErrorStream());
            } catch(IOException ignored) {
            }
        }
        c.disconnect();
    }
}
