// Copyright 2012 Google Inc. All Rights Reserved.
//
// 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.gitiles;

import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gitiles.CommitData.Field;
import com.google.template.soy.jbcsrc.api.SoySauce;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;

public class LogSoyData {
  private static final ImmutableSet<Field> FIELDS =
      Sets.immutableEnumSet(
          Field.ABBREV_SHA,
          Field.SHA,
          Field.URL,
          Field.SHORT_MESSAGE,
          Field.MESSAGE,
          Field.AUTHOR,
          Field.COMMITTER,
          Field.BRANCHES,
          Field.TAGS);
  private static final ImmutableSet<Field> VERBOSE_FIELDS = Field.setOf(FIELDS, Field.DIFF_TREE);

  /** Behavior for the footer link when rendering streaming log data. */
  public enum FooterBehavior {
    /** "Next" link that skips commits in the current view. */
    NEXT,

    /** "More" link that starts from HEAD. */
    LOG_HEAD;
  }

  private final HttpServletRequest req;
  private final GitilesView view;
  private final Set<Field> fields;
  private final String variant;
  private CommitSoyData csd;

  public LogSoyData(HttpServletRequest req, GitilesAccess access, String pretty)
      throws IOException {
    this.req = checkNotNull(req);
    this.view = checkNotNull(ViewFilter.getView(req));
    checkNotNull(pretty);
    Config config = access.getConfig();
    fields =
        config.getBoolean("logFormat", pretty, "verbose", false) || pretty.equals("fuller")
            ? VERBOSE_FIELDS
            : FIELDS;
    variant = firstNonNull(config.getString("logFormat", pretty, "variant"), pretty);
  }

  private void renderHtml(SoySauce.Renderer renderer, Appendable out) throws IOException {
    if (!renderer.renderHtml(out).result().isDone()) {
      throw new IOException("failed to render HTML");
    }
  }

  public void renderStreaming(
      Paginator paginator,
      @Nullable String revision,
      Renderer renderer,
      Writer writer,
      DateFormatter df,
      FooterBehavior footerBehavior)
      throws IOException {
    renderHtml(
        renderer
            .newRenderer("com.google.gitiles.templates.LogDetail.logEntriesHeader")
            .setData(toHeaderSoyData(paginator, revision)),
        writer);

    SoySauce.Renderer entryRenderer =
        renderer.newRenderer("com.google.gitiles.templates.LogDetail.logEntryWrapper");
    boolean renderedEntries = false;
    for (RevCommit c : paginator) {
      renderHtml(entryRenderer.setData(toEntrySoyData(paginator, c, df)), writer);
      renderedEntries = true;
    }
    if (!renderedEntries) {
      renderHtml(renderer.newRenderer("com.google.gitiles.templates.LogDetail.emptyLog"), writer);
    }

    renderHtml(
        renderer
            .newRenderer("com.google.gitiles.templates.LogDetail.logEntriesFooter")
            .setData(toFooterSoyData(paginator, revision, footerBehavior)),
        writer);
  }

  private Map<String, Object> toHeaderSoyData(Paginator paginator, @Nullable String revision) {
    Map<String, Object> data = Maps.newHashMapWithExpectedSize(1);
    ObjectId prev = paginator.getPreviousStart();
    if (prev != null) {
      GitilesView.Builder prevView = copyAndCanonicalizeView(revision);
      if (prevView.getRevision().getId().equals(prev)) {
        prevView.removeParam(LogServlet.START_PARAM);
      } else {
        prevView.replaceParam(LogServlet.START_PARAM, prev.name());
      }
      data.put("previousUrl", prevView.toUrl());
    }
    return data;
  }

  private Map<String, Object> toEntrySoyData(Paginator paginator, RevCommit c, DateFormatter df)
      throws IOException {
    if (csd == null) {
      csd = new CommitSoyData();
    }

    Map<String, Object> entry = csd.toSoyData(req, paginator.getWalk(), c, fields, df);
    DiffEntry rename = paginator.getRename(c);
    if (rename != null) {
      entry.put("rename", toRenameSoyData(rename));
    }
    return ImmutableMap.of(
        "variant", variant,
        "entry", entry);
  }

  private @Nullable Map<String, Object> toRenameSoyData(DiffEntry entry) {
    if (entry == null) {
      return null;
    }
    ChangeType type = entry.getChangeType();
    if (type != ChangeType.RENAME && type != ChangeType.COPY) {
      return null;
    }
    return ImmutableMap.<String, Object>of(
        "changeType", type.toString(),
        "oldPath", entry.getOldPath(),
        "newPath", entry.getNewPath(),
        "score", entry.getScore());
  }

  private Map<String, Object> toFooterSoyData(
      Paginator paginator, @Nullable String revision, FooterBehavior behavior) {
    switch (behavior) {
      case NEXT:
        ObjectId next = paginator.getNextStart();
        if (next == null) {
          return ImmutableMap.of();
        }
        return ImmutableMap.of(
            "nextUrl",
            copyAndCanonicalizeView(revision)
                .replaceParam(LogServlet.START_PARAM, next.name())
                .toUrl(),
            "nextText",
            "Next");

      case LOG_HEAD:
        return ImmutableMap.of(
            "nextUrl", GitilesView.log().copyFrom(view).toUrl(), "nextText", "More");
      default:
        throw new IllegalStateException("unknown footer behavior: " + behavior);
    }
  }

  private GitilesView.Builder copyAndCanonicalizeView(String revision) {
    // Canonicalize the view by using full SHAs.
    GitilesView.Builder copy = GitilesView.log().copyFrom(view);
    if (!Revision.isNull(view.getRevision())) {
      copy.setRevision(view.getRevision());
    } else if (revision != null) {
      copy.setRevision(Revision.named(revision));
    } else {
      copy.setRevision(Revision.NULL);
    }
    if (!Revision.isNull(view.getOldRevision())) {
      copy.setOldRevision(view.getOldRevision());
    }
    return copy;
  }
}
