/*
 * 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.cli.impl.jira;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.lang.reflect.Type;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.apache.http.HttpHeaders;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.sling.cli.impl.ComponentContextHelper;
import org.apache.sling.cli.impl.DateProvider;
import org.apache.sling.cli.impl.http.HttpClientFactory;
import org.apache.sling.cli.impl.release.Release;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.util.promise.FailedPromisesException;
import org.osgi.util.promise.Promise;
import org.osgi.util.promise.PromiseFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.Gson;
import com.google.gson.JsonIOException;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonWriter;

/**
 * Access the ASF <em>Jira</em> instance and looks up project version data.
 */
@Component(service = VersionClient.class)
public class VersionClient {

    private static final Logger LOGGER = LoggerFactory.getLogger(VersionClient.class);

    private static final String PROJECT_KEY = "SLING";
    private static final String DEFAULT_JIRA_URL = "https://issues.apache.org/jira";
    private static final String CONTENT_TYPE_JSON = "application/json";

    private final PromiseFactory promiseFactory = new PromiseFactory(null, null);

    @Reference
    private HttpClientFactory httpClientFactory;

    @Reference
    private DateProvider dateProvider;

    private String jiraRESTAPIEntrypoint;
    private String jiraURL;

    @Activate
    protected void activate(ComponentContext ctx) {
        ComponentContextHelper helper = ComponentContextHelper.wrap(ctx);
        jiraURL = helper.getProperty("jira.url", DEFAULT_JIRA_URL);
        jiraRESTAPIEntrypoint = jiraURL + "/rest/api/2/";
    }

    /**
     * Finds a Jira version which matches the specified release
     * 
     * @param release the release
     * @return the version
     * @throws IllegalArgumentException when no matching Jira release is found
     */
    public Version find(Release release) {
        Version version;
        
        try (CloseableHttpClient client = httpClientFactory.newClient()) {
            version = findVersion( v -> release.getName().equals(v.getName()), client)
                    .orElseThrow( () -> new IllegalArgumentException("No version found with name " + release.getName()));
            populateRelatedIssuesCount(client, version);
        } catch ( IOException e ) {
            throw new RuntimeException(e);
        }
        
        return version;
    }

    /**
     * Finds a version that is the successor of the version of the specified
     * <tt>release</tt>
     * 
     * <p>
     * A successor has the same base name but a higher version. For instance, the
     * <em>XSS Protection API 2.1.6</em> is succeeded by <em>XSS Protection API
     * 2.1.8</em>.
     * </p>
     * 
     * <p>
     * If multiple successors are found the one which is closest in terms of
     * versioning is returned.
     * </p>
     * 
     * @param release the release to find a successor for
     * @return the successor version, possibly <code>null</code>
     */
    public Version findSuccessorVersion(Release release) {
        Version version;
        
        try (CloseableHttpClient client = httpClientFactory.newClient()) {
            Optional<Version> opt = findVersion ( 
                    v -> isFollowingVersion(Release.fromString(v.getName()).get(0), release)
                    ,client);
            if (opt.isEmpty())
                return null;
            version = opt.get();
            populateRelatedIssuesCount(client, version);
        } catch ( IOException e ) {
            throw new RuntimeException(e);
        }
        
        return version;
    }
    
    /**
     * Creates a version with the specified name
     * 
     * <p>The version will be created for the {@value #PROJECT_KEY} project.</p>
     * 
     * @param versionName the name of the version
     * @throws IOException In case of any errors creating the version in Jira
     */
    public void create(String versionName) throws IOException {
        
        StringWriter w = new StringWriter();
        try ( JsonWriter jw = new Gson().newJsonWriter(w) ) {
            jw.beginObject();
            jw.name("name").value(versionName);
            jw.name("project").value(PROJECT_KEY);
            jw.endObject();
        }
        
        HttpPost post = newPost("version");
        post.setEntity(new StringEntity(w.toString()));

        try (CloseableHttpClient client = httpClientFactory.newClient()) {
            try (CloseableHttpResponse response = client.execute(post, httpClientFactory.newPreemptiveAuthenticationContext())) {
                try (InputStream content = response.getEntity().getContent();
                        InputStreamReader reader = new InputStreamReader(content)) {
                    
                    if (response.getStatusLine().getStatusCode() != 201) {
                        throw newException(response, reader);
                    }
                }
            }
        }
    }

    private HttpGet newGet(String suffix) {
        HttpGet get = new HttpGet(jiraRESTAPIEntrypoint + suffix);
        get.addHeader(HttpHeaders.ACCEPT, CONTENT_TYPE_JSON);
        return get;
    }

    private HttpPost newPost(String suffix) {
        HttpPost post = new HttpPost(jiraRESTAPIEntrypoint + suffix);
        post.addHeader(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE_JSON);
        post.addHeader(HttpHeaders.ACCEPT, CONTENT_TYPE_JSON);
        return post;
    }
    
    private HttpPut newPut(String suffix) {
        HttpPut put = new HttpPut(jiraRESTAPIEntrypoint + suffix);
        put.addHeader(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE_JSON);
        put.addHeader(HttpHeaders.ACCEPT, CONTENT_TYPE_JSON);
        return put;
    }
    
    public List<Issue> findUnresolvedIssues(Release release) throws IOException {
        return findIssues(release).stream().filter(issue -> issue.getResolution() == null).collect(Collectors.toList());
    }

    public List<Issue> findFixedIssues(Release release) throws IOException {
        return findIssues(release).stream().filter(issue -> issue.getResolution() != null).collect(Collectors.toList());
    }

    private void closeIssues(List<Issue> issues) throws Exception {
        List<Promise<Issue>> closedIssues = new ArrayList<>();
        for (Issue issue : issues) {
            if (!"Closed".equals(issue.getStatus())) {
                closedIssues.add(getCloseTransition(issue).then(closeTransition -> closeIssue(issue, closeTransition.getValue())));
            }
        }
        Promise<List<Issue>> closedFixedIssues = promiseFactory.all(closedIssues);
        Throwable failed = closedFixedIssues.getFailure();
        if (failed != null) {
            if (failed instanceof FailedPromisesException) {
                FailedPromisesException failedPromisesException = (FailedPromisesException) failed;
                StringBuilder failureMessages = new StringBuilder();
                for (Promise<?> promise : failedPromisesException.getFailedPromises()) {
                    failureMessages.append(promise.getFailure().getMessage()).append("\n");
                }
                throw new IOException("Unable to close the following issues:\n" + failureMessages.toString());
            } else {
                throw new Exception(failed);
            }
        }
    }

    public void release(Release release) throws Exception {
        List<Issue> issues = findIssues(release);
        List<Issue> unresolvedIssues = new ArrayList<>();
        issues.forEach(issue -> {
            if (issue.getResolution() == null) {
                unresolvedIssues.add(issue);
            }
        });
        if (unresolvedIssues.isEmpty()) {
            closeIssues(issues);
            Version version = find(release);
            if (!version.isReleased()) {
                HttpPut put = newPut("version/" + version.getId());
                StringWriter w = new StringWriter();
                try (JsonWriter jw = new Gson().newJsonWriter(w)) {
                    jw.beginObject().name("released").value(true).name("releaseDate").value(dateProvider.getCurrentDateForJiraRelease())
                            .endObject();
                }
                put.setEntity(new StringEntity(w.toString()));
                try (CloseableHttpClient client = httpClientFactory.newClient()) {
                    try (CloseableHttpResponse response = client.execute(put, httpClientFactory.newPreemptiveAuthenticationContext())) {
                        int statusCode = response.getStatusLine().getStatusCode();
                        if (statusCode != 200) {
                            throw new IOException(String.format("Unable to mark %s as released. Got status code %d.", release.getFullName(),
                                    statusCode));
                        }
                    }
                }
            } else {
                LOGGER.info("Version {} was already released on {}.", version.getName(), version.getReleaseDate());
            }
        } else {
            String report =
                    unresolvedIssues.stream().map(issue -> String.format("%s/browse/%s", jiraURL, issue.getKey())).collect(Collectors.joining(System.lineSeparator()));
            throw new IllegalStateException("The following issues are not fixed:\n" + report);
        }
    }

    private List<Issue> findIssues(Release release) throws IOException {
        try {
            HttpGet get = newGet("search");
            URIBuilder builder = new URIBuilder(get.getURI());
            builder.addParameter("jql",
                    String.format("project = %s AND fixVersion = \"%s\"", PROJECT_KEY, release.getName()));
            builder.addParameter("fields", "summary,status,resolution");
            get.setURI(builder.build());

            try (CloseableHttpClient client = httpClientFactory.newClient()) {
                try (CloseableHttpResponse response = client.execute(get)) {
                    try (InputStream content = response.getEntity().getContent();
                         InputStreamReader reader = new InputStreamReader(content)) {

                        if (response.getStatusLine().getStatusCode() != 200) {
                            throw newException(response, reader);
                        }

                        Gson gson = new Gson();
                        return gson.fromJson(reader, IssueResponse.class).getIssues();
                    }
                }
            }
        } catch (URISyntaxException e) {
            throw new IllegalArgumentException(e);
        }
    }

    private IOException newException(CloseableHttpResponse response, InputStreamReader reader) {
        
        StringBuilder message = new StringBuilder();
        message.append("Status line : ").append(response.getStatusLine());
        
        try {
            Gson gson = new Gson();
            ErrorResponse errors = gson.fromJson(reader, ErrorResponse.class);
            if ( errors != null ) {
                if ( !errors.getErrorMessages().isEmpty() )
                    message.append(". Error messages: ")
                        .append(errors.getErrorMessages());
                
                if ( !errors.getErrors().isEmpty() )
                    errors.getErrors().forEach((key, value) -> message.append(". Error for ").append(key).append(" : ").append(value));
            }
        } catch ( JsonIOException | JsonSyntaxException e) {
            message.append(". Failed parsing response as JSON ( ")
                .append(e.getMessage())
                .append(" )");
        }
        
        return new IOException(message.toString());
    }

    private Optional<Version> findVersion(Predicate<Version> matcher, CloseableHttpClient client) throws IOException {
        
        HttpGet get = newGet("project/" + PROJECT_KEY + "/versions");
        try (CloseableHttpResponse response = client.execute(get)) {
            try (InputStream content = response.getEntity().getContent();
                    InputStreamReader reader = new InputStreamReader(content)) {
                if (response.getStatusLine().getStatusCode() != 200)
                    throw newException(response, reader);
                
                Gson gson = new Gson();
                Type collectionType = TypeToken.getParameterized(List.class, Version.class).getType();
                List<Version> versions = gson.fromJson(reader, collectionType);
                return versions.stream()
                        .filter( v -> v.getName().length() > 1) // avoid old '3' release
                        .filter(matcher)
                        .min(VersionClient::compare);
            }
        }
    }
        
    private void populateRelatedIssuesCount(CloseableHttpClient client, Version version) throws IOException {
        
        HttpGet get = newGet("version/" + version.getId() +"/relatedIssueCounts");
        try (CloseableHttpResponse response = client.execute(get)) {
            try (InputStream content = response.getEntity().getContent();
                    InputStreamReader reader = new InputStreamReader(content)) {
                if (response.getStatusLine().getStatusCode() != 200)
                    throw newException(response, reader);

                Gson gson = new Gson();
                VersionRelatedIssuesCount issuesCount = gson.fromJson(reader, VersionRelatedIssuesCount.class);
                
                version.setRelatedIssuesCount(issuesCount.getIssuesFixedCount());
            }
        }
    }

    private boolean isFollowingVersion(Release base, Release candidate) {
        return base.getComponent().equals(candidate.getComponent())
                && new org.osgi.framework.Version(base.getVersion())
                    .compareTo(new org.osgi.framework.Version(candidate.getVersion())) > 0;
    }
    
    private static int compare(Version v1, Version v2) {
        // version names will never map to multiple release names
        Release r1 = Release.fromString(v1.getName()).get(0);
        Release r2 = Release.fromString(v2.getName()).get(0);
        
        org.osgi.framework.Version ver1 = new org.osgi.framework.Version(r1.getVersion());
        org.osgi.framework.Version ver2 = new org.osgi.framework.Version(r2.getVersion());
        
        return ver1.compareTo(ver2);
    }

    static class VersionRelatedIssuesCount {

        private int issuesFixedCount;

        public int getIssuesFixedCount() {
            return issuesFixedCount;
        }

        @SuppressWarnings("unused")
        public void setIssuesFixedCount(int issuesFixedCount) {
            this.issuesFixedCount = issuesFixedCount;
        }
    }

    public void moveIssuesToNewVersion(Version oldVersion, Version newVersion, List<Issue> issues) {
        issues.forEach( i -> moveIssueToNewVersion(oldVersion, newVersion, i));
        
    }
    
    private void moveIssueToNewVersion(Version oldVersion, Version newVersion, Issue issue) {
        try {
            StringWriter w = new StringWriter();
            
            IssueUpdate update = new IssueUpdate();
            update.recordAdd("fixVersions", newVersion.getName());
            update.recordRemove("fixVersions", oldVersion.getName());
            Gson gson = new Gson();
            gson.toJson(update, w);
            
            HttpPut put = newPut("issue/" + issue.getKey());
            put.setEntity(new StringEntity(w.toString(), StandardCharsets.UTF_8));

            try (CloseableHttpClient client = httpClientFactory.newClient()) {
                try (CloseableHttpResponse response = client.execute(put, httpClientFactory.newPreemptiveAuthenticationContext())) {
                    if (response.getStatusLine().getStatusCode() != 204) {
                        try (InputStream content = response.getEntity().getContent();
                                InputStreamReader reader = new InputStreamReader(content)) {
                                throw newException(response, reader);
                        }
                    }
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private Promise<Transition> getCloseTransition(Issue issue) {
        HttpGet get = newGet("issue/" + issue.getId() + "/transitions");
        try {
            try (CloseableHttpClient client = httpClientFactory.newClient()) {
                try (CloseableHttpResponse getResponse = client.execute(get, httpClientFactory.newPreemptiveAuthenticationContext())) {
                    try (InputStream getContent = getResponse.getEntity().getContent();
                         InputStreamReader getReader = new InputStreamReader(getContent)) {
                        if (getResponse.getStatusLine().getStatusCode() != 200) {
                            throw newException(getResponse, getReader);
                        }
                        Gson gson = new Gson();
                        List<Transition> transitions = gson.fromJson(getReader, TransitionsResponse.class).getTransitions();
                        Optional<Transition> transition = transitions.stream().filter(t -> "Close Issue".equals(t.getName())).findFirst();
                        if (transition.isPresent()) {
                            return promiseFactory.resolved(transition.get());
                        } else {
                            return promiseFactory
                                    .failed(new IllegalStateException(String.format("Issue %s/browse/%s cannot be closed - missing Close " +
                                                    "transition.", jiraURL,
                                            issue.getKey())));
                        }
                    }
                }
            }
        } catch (Exception e) {
            return promiseFactory.failed(e);
        }
    }

    private Promise<Issue> closeIssue(Issue issue, Transition closeTransition) {
        HttpPost post = newPost("issue/" + issue.getId() + "/transitions");
        StringWriter w = new StringWriter();
        try (JsonWriter jw = new Gson().newJsonWriter(w)) {
            jw.beginObject().name("transition").beginObject().name("id").value(closeTransition.getId()).endObject().endObject();
            post.setEntity(new StringEntity(w.toString()));
            try (CloseableHttpClient client = httpClientFactory.newClient()) {
                try (CloseableHttpResponse postResponse = client.execute(post, httpClientFactory.newPreemptiveAuthenticationContext())) {
                    if (postResponse.getStatusLine().getStatusCode() == 204) {
                        return promiseFactory.resolved(issue);
                    } else {
                        return promiseFactory.failed(new RuntimeException(String.format("Unable to close issue %s/browse/%s - got status code %d.",
                         jiraURL, issue.getKey(), postResponse.getStatusLine().getStatusCode())));
                    }
                }
            }
        } catch (IOException e) {
            return promiseFactory.failed(e);
        }
    }
}
