// Copyright (C) 2014 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.google.gerrit.server.query.change;

import static com.google.common.base.Preconditions.checkState;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.Lists;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.common.PluginDefinedInfo;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.QueryResult;
import com.google.gerrit.server.DynamicOptions;
import com.google.gerrit.server.account.AccountAttributeLoader;
import com.google.gerrit.server.config.TrackingFooters;
import com.google.gerrit.server.data.ChangeAttribute;
import com.google.gerrit.server.data.PatchSetAttribute;
import com.google.gerrit.server.data.QueryStatsAttribute;
import com.google.gerrit.server.events.EventFactory;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.project.SubmitRuleEvaluator;
import com.google.gerrit.server.project.SubmitRuleOptions;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gson.Gson;
import com.google.inject.Inject;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.io.DisabledOutputStream;

/**
 * Change query implementation that outputs to a stream in the style of an SSH command.
 *
 * <p>Instances are one-time-use. Other singleton classes should inject a Provider rather than
 * holding on to a single instance.
 */
public class OutputStreamQuery {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private static final DateTimeFormatter dtf =
      DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss zzz")
          .withLocale(Locale.US)
          .withZone(ZoneId.systemDefault());

  public enum OutputFormat {
    TEXT,
    JSON
  }

  public static final Gson GSON = new Gson();

  private final GitRepositoryManager repoManager;
  private final ChangeQueryBuilder queryBuilder;
  private final ChangeQueryProcessor queryProcessor;
  private final EventFactory eventFactory;
  private final TrackingFooters trackingFooters;
  private final SubmitRuleEvaluator.Factory submitRuleEvaluatorFactory;
  private final AccountAttributeLoader.Factory accountAttributeLoaderFactory;

  private OutputFormat outputFormat = OutputFormat.TEXT;
  private boolean includePatchSets;
  private boolean includeCurrentPatchSet;
  private boolean includeApprovals;
  private boolean includeComments;
  private boolean includeFiles;
  private boolean includeCommitMessage;
  private boolean includeDependencies;
  private boolean includeSubmitRecords;
  private boolean includeAllReviewers;

  private OutputStream outputStream = DisabledOutputStream.INSTANCE;
  private PrintWriter out;
  private ImmutableListMultimap<Change.Id, PluginDefinedInfo> pluginInfosByChange =
      ImmutableListMultimap.of();

  @Inject
  OutputStreamQuery(
      GitRepositoryManager repoManager,
      ChangeQueryBuilder queryBuilder,
      ChangeQueryProcessor queryProcessor,
      EventFactory eventFactory,
      TrackingFooters trackingFooters,
      SubmitRuleEvaluator.Factory submitRuleEvaluatorFactory,
      AccountAttributeLoader.Factory accountAttributeLoaderFactory) {
    this.repoManager = repoManager;
    this.queryBuilder = queryBuilder;
    this.queryProcessor = queryProcessor;
    this.eventFactory = eventFactory;
    this.trackingFooters = trackingFooters;
    this.submitRuleEvaluatorFactory = submitRuleEvaluatorFactory;
    this.accountAttributeLoaderFactory = accountAttributeLoaderFactory;
  }

  void setLimit(int n) {
    queryProcessor.setUserProvidedLimit(n, /* applyDefaultLimit */ false);
  }

  public void setNoLimit(boolean on) {
    queryProcessor.setNoLimit(on);
  }

  public void setStart(int n) {
    queryProcessor.setStart(n);
  }

  public void setIncludePatchSets(boolean on) {
    includePatchSets = on;
  }

  public boolean getIncludePatchSets() {
    return includePatchSets;
  }

  public void setIncludeCurrentPatchSet(boolean on) {
    includeCurrentPatchSet = on;
  }

  public boolean getIncludeCurrentPatchSet() {
    return includeCurrentPatchSet;
  }

  public void setIncludeApprovals(boolean on) {
    includeApprovals = on;
  }

  public void setIncludeComments(boolean on) {
    includeComments = on;
  }

  public void setIncludeFiles(boolean on) {
    includeFiles = on;
  }

  public boolean getIncludeFiles() {
    return includeFiles;
  }

  public void setIncludeDependencies(boolean on) {
    includeDependencies = on;
  }

  public boolean getIncludeDependencies() {
    return includeDependencies;
  }

  public void setIncludeCommitMessage(boolean on) {
    includeCommitMessage = on;
  }

  public void setIncludeSubmitRecords(boolean on) {
    includeSubmitRecords = on;
  }

  public void setIncludeAllReviewers(boolean on) {
    includeAllReviewers = on;
  }

  public void setOutput(OutputStream out, OutputFormat fmt) {
    this.outputStream = out;
    this.outputFormat = fmt;
  }

  public void setDynamicBean(String plugin, DynamicOptions.DynamicBean dynamicBean) {
    queryProcessor.setDynamicBean(plugin, dynamicBean);
  }

  public void query(String queryString) throws IOException {
    out =
        new PrintWriter( //
            new BufferedWriter( //
                new OutputStreamWriter(outputStream, UTF_8)));
    try {
      if (queryProcessor.isDisabled()) {
        ErrorMessage m = new ErrorMessage();
        m.message = "query disabled";
        show(m);
        return;
      }

      try {
        final QueryStatsAttribute stats = new QueryStatsAttribute();
        stats.runTimeMilliseconds = TimeUtil.nowMs();

        Map<Project.NameKey, Repository> repos = new HashMap<>();
        Map<Project.NameKey, RevWalk> revWalks = new HashMap<>();
        QueryResult<ChangeData> results = queryProcessor.query(queryBuilder.parse(queryString));
        pluginInfosByChange = queryProcessor.createPluginDefinedInfos(results.entities());
        try {
          AccountAttributeLoader accountLoader = accountAttributeLoaderFactory.create();
          List<ChangeAttribute> changeAttributes = new ArrayList<>();
          for (ChangeData d : results.entities()) {
            changeAttributes.add(buildChangeAttribute(d, repos, revWalks, accountLoader));
          }
          accountLoader.fill();
          changeAttributes.forEach(c -> show(c));
        } finally {
          closeAll(revWalks.values(), repos.values());
        }

        stats.rowCount = results.entities().size();
        stats.moreChanges = results.more();
        stats.runTimeMilliseconds = TimeUtil.nowMs() - stats.runTimeMilliseconds;
        show(stats);
      } catch (StorageException err) {
        logger.atSevere().withCause(err).log("Cannot execute query: %s", queryString);

        ErrorMessage m = new ErrorMessage();
        m.message = "cannot query database";
        show(m);

      } catch (QueryParseException e) {
        ErrorMessage m = new ErrorMessage();
        m.message = e.getMessage();
        show(m);
      }
    } finally {
      try {
        out.flush();
      } finally {
        out = null;
      }
    }
  }

  private ChangeAttribute buildChangeAttribute(
      ChangeData d,
      Map<Project.NameKey, Repository> repos,
      Map<Project.NameKey, RevWalk> revWalks,
      AccountAttributeLoader accountLoader)
      throws IOException {
    ChangeAttribute c = eventFactory.asChangeAttribute(d.change(), accountLoader);
    c.hashtags = Lists.newArrayList(d.hashtags());
    eventFactory.extend(c, d.change());

    if (!trackingFooters.isEmpty()) {
      eventFactory.addTrackingIds(c, d.trackingFooters());
    }

    if (includeAllReviewers) {
      eventFactory.addAllReviewers(c, d.notes(), accountLoader);
    }

    if (includeSubmitRecords) {
      SubmitRuleOptions options =
          SubmitRuleOptions.builder().recomputeOnClosedChanges(true).build();
      eventFactory.addSubmitRecords(
          c, submitRuleEvaluatorFactory.create(options).evaluate(d), accountLoader);
    }

    if (includeCommitMessage) {
      eventFactory.addCommitMessage(c, d.commitMessage());
    }

    if (includePatchSets || includeCurrentPatchSet || includeDependencies) {
      Project.NameKey p = d.change().getProject();
      Repository repo;
      RevWalk rw = revWalks.get(p);
      // Cache and reuse repos and revwalks.
      if (rw == null) {
        repo = repoManager.openRepository(p);
        checkState(repos.put(p, repo) == null);
        rw = new RevWalk(repo);
        revWalks.put(p, rw);
      } else {
        repo = repos.get(p);
      }

      if (includePatchSets) {
        eventFactory.addPatchSets(
            rw,
            repo.getConfig(),
            c,
            includeApprovals ? d.conditionallyLoadApprovalsWithCopied().asMap() : null,
            includeFiles,
            d,
            accountLoader);
        if (includeComments) {
          for (PatchSetAttribute attribute : c.patchSets) {
            eventFactory.addPatchSetComments(attribute, d.publishedComments(), accountLoader);
          }
        }
      }

      if (includeCurrentPatchSet) {
        PatchSet current = d.currentPatchSet();
        if (current != null) {
          c.currentPatchSet =
              eventFactory.asPatchSetAttribute(rw, repo.getConfig(), d, current, accountLoader);
          eventFactory.addApprovals(
              c.currentPatchSet, d.currentApprovals(), d.getLabelTypes(), accountLoader);

          if (includeFiles) {
            eventFactory.addPatchSetFileNames(c.currentPatchSet, d.change(), d.currentPatchSet());
          }
          if (includeComments) {
            eventFactory.addPatchSetComments(
                c.currentPatchSet, d.publishedComments(), accountLoader);
          }
        }
      }

      if (includeDependencies) {
        eventFactory.addDependencies(rw, c, d.change(), d.currentPatchSet());
      }
    }

    if (includeComments) {
      eventFactory.addComments(c, d.messages(), accountLoader);
    }

    ImmutableList<PluginDefinedInfo> pluginInfos = pluginInfosByChange.get(d.getId());
    if (!pluginInfos.isEmpty()) {
      c.plugins = pluginInfos;
    }
    return c;
  }

  private static void closeAll(Iterable<RevWalk> revWalks, Iterable<Repository> repos) {
    if (repos != null) {
      for (Repository repo : repos) {
        repo.close();
      }
    }
    if (revWalks != null) {
      for (RevWalk revWalk : revWalks) {
        revWalk.close();
      }
    }
  }

  private void show(Object data) {
    switch (outputFormat) {
      default:
      case TEXT:
        if (data instanceof ChangeAttribute) {
          out.print("change ");
          out.print(((ChangeAttribute) data).id);
          out.print("\n");
          showText(data, 1);
        } else {
          showText(data, 0);
        }
        out.print('\n');
        break;

      case JSON:
        out.print(GSON.toJson(data));
        out.print('\n');
        break;
    }
  }

  private void showText(Object data, int depth) {
    for (Field f : fieldsOf(data.getClass())) {
      Object val;
      try {
        val = f.get(data);
      } catch (IllegalArgumentException err) {
        continue;
      } catch (IllegalAccessException err) {
        continue;
      }
      if (val == null) {
        continue;
      }

      showField(f.getName(), val, depth);
    }
  }

  private String indent(int spaces) {
    if (spaces == 0) {
      return "";
    }
    return String.format("%" + spaces + "s", " ");
  }

  private void showField(String field, Object value, int depth) {
    final int spacesDepthRatio = 2;
    String indent = indent(depth * spacesDepthRatio);
    out.print(indent);
    out.print(field);
    out.print(':');
    if (value instanceof String && ((String) value).contains("\n")) {
      out.print(' ');
      // Idention for multi-line text is
      // current depth indetion + length of field + length of ": "
      indent = indent(indent.length() + field.length() + spacesDepthRatio);
      out.print(((String) value).replace("\n", "\n" + indent).trim());
      out.print('\n');
    } else if (value instanceof Long && isDateField(field)) {
      out.print(' ');
      out.print(dtf.format(Instant.ofEpochSecond((Long) value)));
      out.print('\n');
    } else if (isPrimitive(value)) {
      out.print(' ');
      out.print(value);
      out.print('\n');
    } else if (value instanceof Collection) {
      out.print('\n');
      boolean firstElement = true;
      for (Object thing : ((Collection<?>) value)) {
        // The name of the collection was initially printed at the beginning
        // of this routine.  Beginning at the second sub-element, reprint
        // the collection name so humans can separate individual elements
        // with less strain and error.
        //
        if (firstElement) {
          firstElement = false;
        } else {
          out.print(indent);
          out.print(field);
          out.print(":\n");
        }
        if (isPrimitive(thing)) {
          out.print(' ');
          out.print(value);
          out.print('\n');
        } else {
          showText(thing, depth + 1);
        }
      }
    } else {
      out.print('\n');
      showText(value, depth + 1);
    }
  }

  private static boolean isPrimitive(Object value) {
    return value instanceof String //
        || value instanceof Number //
        || value instanceof Boolean //
        || value instanceof Enum;
  }

  private static boolean isDateField(String name) {
    return "lastUpdated".equals(name) //
        || "grantedOn".equals(name) //
        || "timestamp".equals(name) //
        || "createdOn".equals(name);
  }

  private List<Field> fieldsOf(Class<?> type) {
    List<Field> r = new ArrayList<>();
    if (type.getSuperclass() != null) {
      r.addAll(fieldsOf(type.getSuperclass()));
    }
    r.addAll(Arrays.asList(type.getDeclaredFields()));
    return r;
  }

  static class ErrorMessage {
    public final String type = "error";
    public String message;
  }
}
