/**
 * Copyright (c) 2015 Codetrails GmbH.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */
package org.eclipse.epp.internal.logging.aeri.ide.server.mars;

import static com.google.common.base.Charsets.UTF_8;
import static java.lang.System.getProperty;
import static org.apache.commons.lang3.ArrayUtils.contains;
import static org.apache.commons.lang3.StringUtils.*;
import static org.eclipse.epp.internal.logging.aeri.ide.server.Proxies.*;
import static org.eclipse.epp.internal.logging.aeri.ide.server.mars.ServerResponse.KEYWORD_NEEDINFO;
import static org.eclipse.epp.logging.aeri.core.ProblemStatus.*;
import static org.eclipse.epp.logging.aeri.core.util.Links.REL_BUG;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.entity.GzipCompressingEntity;
import org.apache.http.client.fluent.Executor;
import org.apache.http.client.fluent.Request;
import org.apache.http.client.fluent.Response;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.epp.internal.logging.aeri.ide.l10n.LogMessages;
import org.eclipse.epp.internal.logging.aeri.ide.l10n.Messages;
import org.eclipse.epp.internal.logging.aeri.ide.server.Proxies;
import org.eclipse.epp.internal.logging.aeri.ide.server.json.Json;
import org.eclipse.epp.logging.aeri.core.ILink;
import org.eclipse.epp.logging.aeri.core.IModelFactory;
import org.eclipse.epp.logging.aeri.core.IProblemState;
import org.eclipse.epp.logging.aeri.core.IReport;
import org.eclipse.epp.logging.aeri.core.ProblemStatus;
import org.eclipse.epp.logging.aeri.core.util.Formats;
import org.eclipse.epp.logging.aeri.core.util.Links;
import org.eclipse.epp.logging.aeri.core.util.Logs;

import com.google.common.annotations.VisibleForTesting;

public class IO {

    private Executor executor;
    private ServerConfiguration configuration;
    private File configurationFile;

    public IO(Executor executor, File configurationFile) {
        this.executor = executor;
        this.configurationFile = configurationFile;
    }

    // TODO test all remote cases for exceptions
    public void refreshConfiguration(String serverUrl, IProgressMonitor monitor)
            throws HttpResponseException, UnknownHostException, Exception {
        Response response = request(newURI(serverUrl), executor);
        String content = HttpResponses.getContentWithProgress(response, monitor);
        configuration = Json.deserialize(content, ServerConfiguration.class);
        configuration.setTimestamp(System.currentTimeMillis());
    }

    public void loadConfiguration() {
        configuration = Json.deserialize(configurationFile, ServerConfiguration.class);
    }

    public void saveConfiguration() {
        Json.serialize(configuration, configurationFile);
    }

    public ServerConfiguration getConfiguration() {
        return configuration;
    }

    public void setConfiguration(ServerConfiguration configuration) {
        this.configuration = configuration;
    }

    public IProblemState upload(IReport report, IProgressMonitor monitor) throws IOException {
        String body = Json.toJson(report, false);
        StringEntity stringEntity = new StringEntity(body, ContentType.APPLICATION_OCTET_STREAM.withCharset(UTF_8));
        // length of zipped conent is unknown, using the progress of the string-stream instead.
        // download progress percentage will be accurate, download progress size will be too large by the compression factor
        HttpEntity entity = new GzipCompressingEntity(HttpResponses.decorateForProgressMonitoring(stringEntity, monitor));

        String submitUrl = configuration.getSubmitUrl();
        URI target = newURI(submitUrl);
        Request request = Request.Post(target).viaProxy(getProxyHost(target).orNull()).body(entity)
                .connectTimeout(configuration.getConnectTimeoutMs()).staleConnectionCheck(true)
                .socketTimeout(configuration.getSocketTimeoutMs());
        setEclipseUuid(request, target);
        String response = proxyAuthentication(executor, target).execute(request).returnContent().asString();
        ServerResponse raw = Json.deserialize(response, ServerResponse.class);

        IProblemState problemState = IModelFactory.eINSTANCE.createProblemState();

        // this looks a bit weird: it's not a bug id but the public id of the submission...
        String submissionUrl = raw.getSubmissionUrl().orNull();
        if (submissionUrl != null) {
            Links.addLink(problemState, Links.REL_SUBMISSION, submissionUrl, Messages.LINK_TEXT_SUBMISSION);
        }
        if (raw.hasBug()) {
            Links.addLink(problemState, REL_BUG, raw.getBugUrl().orNull(),
                    Formats.format(Messages.LINK_TEXT_BUG, raw.getBugId().or(Messages.LINK_TEXT_BUG_ID_NULL)));
        }

        problemState.setStatus(tryParse(raw));
        String message = raw.getInformation().orNull();
        if (message != null && !StringUtils.contains(message, "</a>") && !StringUtils.contains(message, "{link")) { //$NON-NLS-1$
            // TODO temporary for Mars.1 servers in Neon:
            // Server sends an 'additional' status message which may not contain any links. Let's append them in a generic way for Neon.M4
            message += appendLinks(problemState.getLinks());
        }
        problemState.setMessage(message);

        String[] keywords = raw.getKeywords().orNull();
        if (keywords != null) {
            for (String keyword : keywords) {
                problemState.getNeedinfo().add(keyword);
            }
        }

        return problemState;
    }

    // returns a string with all links. Separated by ' ' and with a leading ' ' if the list of links is not empty.
    private String appendLinks(EMap<String, ILink> links) {
        if (links.isEmpty()) {
            return ""; //$NON-NLS-1$
        }
        StringBuilder sb = new StringBuilder();
        for (ILink link : links.values()) {
            sb.append(Formats.format(" {0,link}", link)); //$NON-NLS-1$
        }
        return sb.toString();
    }

    private static URI newURI(String uri) throws IOException {
        try {
            return new URI(uri);
        } catch (URISyntaxException e) {
            throw new IOException("invalid server url: " + uri, e); //$NON-NLS-1$
        }
    }

    /**
     *
     * @param monitor
     * @return the {@link HttpStatus}
     */
    public int downloadDatabase(File destination, IProgressMonitor monitor) throws IOException {
        URI target = newURI(configuration.getProblemsUrl());
        // @formatter:off
        Request request = Request.Get(target)
                .viaProxy(getProxyHost(target).orNull())
                .connectTimeout(configuration.getConnectTimeoutMs())
                .staleConnectionCheck(true)
                .socketTimeout(configuration.getSocketTimeoutMs());
        // @formatter:on
        setEclipseUuid(request, target);

        Response response = Proxies.proxyAuthentication(executor, target).execute(request);

        HttpResponse returnResponse = HttpResponses.getResponseWithProgress(response, monitor);
        int statusCode = returnResponse.getStatusLine().getStatusCode();

        if (statusCode == HttpStatus.SC_OK) {
            configuration.setProblemsZipLastDownloadTimestamp(System.currentTimeMillis());
            saveConfiguration();
            try (FileOutputStream out = new FileOutputStream(destination)) {
                returnResponse.getEntity().writeTo(out);
            }
        }
        return statusCode;
    }

    public boolean isProblemsDatabaseOutdated() {
        return System.currentTimeMillis() - configuration.getProblemsZipLastDownloadTimestamp() > configuration.getProblemsTtlMs();
    }

    public boolean isConfigurationOutdated() {
        if (configuration == null) {
            return true;
        }
        return System.currentTimeMillis() - configuration.getTimestamp() > configuration.getTtlMs();
    }

    @VisibleForTesting
    public static Response request(URI target, Executor executor) throws ClientProtocolException, IOException {
        // max time until a connection to the server has to be established.
        int connectTimeout = (int) TimeUnit.SECONDS.toMillis(3);
        // max time between two packets sent back to the client. 10 seconds of silence will kill the session
        int socketTimeout = (int) TimeUnit.SECONDS.toMillis(10);
        Request request = Request.Get(target).viaProxy(getProxyHost(target).orNull()).connectTimeout(connectTimeout)
                .staleConnectionCheck(true).socketTimeout(socketTimeout);
        setEclipseUuid(request, target);
        return proxyAuthentication(executor, target).execute(request);
    }

    private static void setEclipseUuid(Request request, URI target) {
        try {
            if (!endsWith(target.getHost(), "eclipse.org")) {
                return;
            }
            String eclipseUuid = defaultIfBlank(getProperty("eclipse.uuid"), "unknownUUID");
            request.setHeader("eclipse.uuid", eclipseUuid);
        } catch (Exception e) {
            Logs.warn("Failed to set eclipse.uuid", e);
        }
    }

    @VisibleForTesting
    public static ProblemStatus tryParse(ServerResponse response) {

        boolean needinfo = contains(response.keywords, KEYWORD_NEEDINFO);
        // public enum Status { UNCONFIRMED, NEW, ASSIGNED, RESOLVED, CLOSED, UNKNOWN }
        String status = response.getStatus().or("").toUpperCase(); //$NON-NLS-1$
        // public enum Resolution { UNSPECIFIED, FIXED, DUPLICATE, WONTFIX, WORKSFORME, INVALID, UNKNOWN }
        String resolution = response.getResolved().or("").toUpperCase(); //$NON-NLS-1$

        switch (resolution) {
        case "": //$NON-NLS-1$
        case "UNSPECIFIED": //$NON-NLS-1$
            // TODO UNSPECIFIED + UNCONFIRMED is used by AERI in the case of some internal error... Not sure whether we should keep that as
            // is.
        case "UNDEFINED": //$NON-NLS-1$
        case "UNKNONW": //$NON-NLS-1$
            // TODO investigate whether incorrectly spelt String "UNKNONW" is needed here
        case "UNKNOWN": //$NON-NLS-1$
            if (needinfo) {
                return NEEDINFO;
            } else if (response.created) {
                return NEW;
            }
            switch (status) {
            case "UNCONFIRMED": //$NON-NLS-1$
            case "NEW": //$NON-NLS-1$
            case "ASSIGNED": //$NON-NLS-1$
            case "REOPEN": //$NON-NLS-1$
                return CONFIRMED;
            }
            // TODO happens when server returns UNKNOWN:
            Logs.log(LogMessages.WARN_UNEXPECTED_SERVER_RESPONSE, status, response);
            return UNCONFIRMED;
        case "INVALID": //$NON-NLS-1$
            return INVALID;
        case "FIXED": //$NON-NLS-1$
            return FIXED;
        case "MOVED": //$NON-NLS-1$
        case "NOT_ECLIPSE": //$NON-NLS-1$
        case "WONTFIX": //$NON-NLS-1$
        case "WORKSFORME": //$NON-NLS-1$
        case "DUPLICATE": //$NON-NLS-1$
            return INVALID;
        default:
            return UNCONFIRMED;
        }
    }
}
