// Copyright (C) 2015 The Android Open Source Project
//
// Licensed 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 com.googlesource.gerrit.plugins.manager.repository;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Strings;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;

import com.googlesource.gerrit.plugins.manager.GerritVersionBranch;
import com.googlesource.gerrit.plugins.manager.PluginManagerConfig;
import com.googlesource.gerrit.plugins.manager.gson.SmartGson;
import com.googlesource.gerrit.plugins.manager.gson.SmartJson;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Singleton
public class JenkinsCiPluginsRepository implements PluginsRepository {

  private static final Logger log = LoggerFactory
      .getLogger(JenkinsCiPluginsRepository.class);

  private static final Optional<PluginInfo> noPluginInfo = Optional.absent();

  private final PluginManagerConfig config;

  private HashMap<String, List<PluginInfo>> cache = new HashMap<>();

  static class View {
    String name;
    Job[] jobs;
  }

  static class Job {
    String name;
    String url;
    String color;
  }

  private final Provider<SmartGson> gsonProvider;

  @Inject
  public JenkinsCiPluginsRepository(Provider<SmartGson> gsonProvider,
      PluginManagerConfig config) {
    this.gsonProvider = gsonProvider;
    this.config = config;
  }

  @Override
  public List<PluginInfo> list(String gerritVersion) throws IOException {
    List<PluginInfo> list = cache.get(gerritVersion);
    if(list == null) {
      list = getList(gerritVersion);
      cache.put(gerritVersion, list);
    }
    return list;
  }

  private List<PluginInfo> getList(String gerritVersion) throws IOException {
    SmartGson gson = gsonProvider.get();
    String viewName = "Plugins-" + GerritVersionBranch.getBranch(gerritVersion);
    List<PluginInfo> plugins = new ArrayList<>();

    try {
      Job[] jobs =
          gson.get(config.getJenkinsUrl() + "/view/" + viewName + "/api/json",
              View.class).jobs;

      for (Job job : jobs) {
        if (job.color.equals("blue")) {
          Optional<PluginInfo> pluginInfo = getPluginInfo(gson, job.url);
          if (pluginInfo.isPresent()) {
            plugins.add(pluginInfo.get());
          }
        }
      }
    } catch (FileNotFoundException e) {
      log.warn("No plugins available for Gerrit version " + gerritVersion, e);
    }

    return plugins;
  }

  private Optional<PluginInfo> getPluginInfo(final SmartGson gson, String url)
      throws IOException {
    SmartJson jobDetails = gson.get(url + "/api/json");
    Optional<SmartJson> lastSuccessfulBuild =
        jobDetails.getOptional("lastSuccessfulBuild");

    return lastSuccessfulBuild.transform(
        new Function<SmartJson, Optional<PluginInfo>>() {
          @Override
          public Optional<PluginInfo> apply(SmartJson build) {
            String buildUrl = build.getString("url");
            try {
              return getPluginArtifactInfo(gson, buildUrl);
            } catch (IOException e) {
              log.warn("Cannot retrieve plugin artifact info from {}", buildUrl);
              return noPluginInfo;
            }
          }
        }).or(noPluginInfo);
  }

  private Optional<PluginInfo> getPluginArtifactInfo(SmartGson gson, String url)
      throws IOException {
    SmartJson buildExecution = gson.get(url + "/api/json");
    JsonArray artifacts =
        buildExecution.get("artifacts").get().getAsJsonArray();
    if (artifacts.size() == 0) {
      return Optional.absent();
    }

    Optional<SmartJson> artifactJson = findArtifact(artifacts, ".jar");
    if (!artifactJson.isPresent()) {
      return Optional.absent();
    }

    String pluginPath = artifactJson.get().getString("relativePath");

    String[] pluginPathParts = pluginPath.split("/");
    String pluginName =
        isMavenBuild(pluginPathParts)
            ? fixPluginNameForMavenBuilds(pluginPathParts)
            : pluginPathParts[pluginPathParts.length - 2];

    String pluginUrl =
        String.format("%s/artifact/%s", buildExecution.getString("url"),
            pluginPath);

    String pluginVersion = "";
    Optional<SmartJson> verArtifactJson =
        findArtifact(artifacts, ".jar-version");
    if (verArtifactJson.isPresent()) {
      String versionUrl =
          String.format("%s/artifact/%s", buildExecution.getString("url"),
              verArtifactJson.get().getString("relativePath"));
      try (BufferedReader reader =
          new BufferedReader(new InputStreamReader(
              new URL(versionUrl).openStream()), 4096)) {
        pluginVersion = reader.readLine();
      }
    }

    String sha1 = "";
    for (JsonElement elem : buildExecution.get("actions").get()
        .getAsJsonArray()) {
      SmartJson elemJson = SmartJson.of(elem);
      Optional<SmartJson> lastBuildRevision =
          elemJson.getOptional("lastBuiltRevision");

      if (lastBuildRevision.isPresent()) {
        sha1 = lastBuildRevision.get().getString("SHA1").substring(0, 8);
      }
    }

    return Optional.of(new PluginInfo(pluginName, pluginVersion, sha1,
        pluginUrl));
  }

  private String fixPluginNameForMavenBuilds(String[] pluginPathParts) {
    String mavenPluginFilename =
        StringUtils.substringBeforeLast(
            pluginPathParts[pluginPathParts.length - 1], ".");
    int versionDelim = mavenPluginFilename.indexOf('-');
    return versionDelim > 0 ? mavenPluginFilename
        .substring(0, versionDelim) : mavenPluginFilename;
  }

  private boolean isMavenBuild(String[] pluginPathParts) {
    return pluginPathParts[pluginPathParts.length - 2].equals("target");
  }

  private Optional<SmartJson> findArtifact(JsonArray artifacts, String string) {
    for (int i = 0; i < artifacts.size(); i++) {
      SmartJson artifact = SmartJson.of(artifacts.get(i));
      if (artifact.getString("relativePath").endsWith(string)) {
        return Optional.of(artifact);
      }
    }

    return Optional.absent();
  }
}
