// 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.Preconditions.checkNotNull;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Ints;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.gson.reflect.TypeToken;

import org.eclipse.jgit.http.server.ServletUtils;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefComparator;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.RefAdvertiser;

import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/** Serves an HTML page with all the refs in a repository. */
public class RefServlet extends BaseServlet {
  private static final long serialVersionUID = 1L;

  private final TimeCache timeCache;

  protected RefServlet(GitilesAccess.Factory accessFactory, Renderer renderer,
      TimeCache timeCache) {
    super(renderer, accessFactory);
    this.timeCache = checkNotNull(timeCache, "timeCache");
  }

  @Override
  protected void doGetHtml(HttpServletRequest req, HttpServletResponse res)
      throws IOException {
    if (!ViewFilter.getView(req).getPathPart().isEmpty()) {
      res.setStatus(SC_NOT_FOUND);
      return;
    }
    RevWalk walk = new RevWalk(ServletUtils.getRepository(req));
    List<Map<String, Object>> tags;
    try {
      tags = getTagsSoyData(req, timeCache, walk, 0);
    } finally {
      walk.release();
    }
    renderHtml(req, res, "gitiles.refsDetail",
        ImmutableMap.of("branches", getBranchesSoyData(req, 0), "tags", tags));
  }

  @Override
  protected void doGetText(HttpServletRequest req, HttpServletResponse res)
      throws IOException {
    GitilesView view = ViewFilter.getView(req);
    Map<String, Ref> refs = getRefs(ServletUtils.getRepository(req).getRefDatabase(),
        view.getPathPart());
    TextRefAdvertiser adv = new TextRefAdvertiser(startRenderText(req, res));
    adv.setDerefTags(true);
    adv.send(refs);
    adv.end();
  }

  @Override
  protected void doGetJson(HttpServletRequest req, HttpServletResponse res)
      throws IOException {
    GitilesView view = ViewFilter.getView(req);
    Map<String, Ref> refs = getRefs(ServletUtils.getRepository(req).getRefDatabase(),
        view.getPathPart());
    Map<String, RefJsonData> jsonRefs = new LinkedHashMap<>();
    for (Map.Entry<String, Ref> ref : refs.entrySet()) {
      jsonRefs.put(ref.getKey(), new RefJsonData(ref.getValue()));
    }
    renderJson(req, res, jsonRefs, new TypeToken<Map<String, RefJsonData>>() {}.getType());
  }

  static List<Map<String, Object>> getBranchesSoyData(HttpServletRequest req, int limit)
      throws IOException {
    RefDatabase refdb = ServletUtils.getRepository(req).getRefDatabase();
    Ref head = refdb.getRef(Constants.HEAD);
    Ref headLeaf = head != null && head.isSymbolic() ? head.getLeaf() : null;
    return getRefsSoyData(
        refdb,
        ViewFilter.getView(req),
        Constants.R_HEADS,
        branchComparator(headLeaf),
        headLeaf,
        limit);
  }

  private static Ordering<Ref> branchComparator(Ref headLeaf) {
    if (headLeaf == null) {
      return Ordering.from(RefComparator.INSTANCE);
    }
    final String headLeafName = headLeaf.getName();
    return new Ordering<Ref>() {
      @Override
      public int compare(@Nullable Ref left, @Nullable Ref right) {
        int l = isHead(left) ? 1 : 0;
        int r = isHead(right) ? 1 : 0;
        return r - l;
      }

      private final boolean isHead(Ref ref) {
        return ref != null && ref.getName().equals(headLeafName);
      }
    }.compound(RefComparator.INSTANCE);
  }

  static List<Map<String, Object>> getTagsSoyData(HttpServletRequest req,
      TimeCache timeCache, RevWalk walk, int limit) throws IOException {
    return getRefsSoyData(
        ServletUtils.getRepository(req).getRefDatabase(),
        ViewFilter.getView(req),
        Constants.R_TAGS,
        tagComparator(timeCache, walk),
        null,
        limit);
  }

  private static Ordering<Ref> tagComparator(final TimeCache timeCache, final RevWalk walk) {
    return Ordering.natural().onResultOf(new Function<Ref, Long>() {
      @Override
      public Long apply(Ref ref) {
        try {
          return timeCache.getTime(walk, ref.getObjectId());
        } catch (IOException e) {
          throw new UncheckedExecutionException(e);
        }
      }
    }).reverse().compound(RefComparator.INSTANCE);
  }

  private static List<Map<String, Object>> getRefsSoyData(
      RefDatabase refdb,
      GitilesView view,
      String prefix,
      Ordering<Ref> ordering,
      @Nullable Ref headLeaf,
      int limit) throws IOException {
    Collection<Ref> refs = refdb.getRefs(prefix).values();
    refs = ordering.leastOf(refs, limit > 0 ? Ints.saturatedCast(limit + 1L) : refs.size());
    List<Map<String, Object>> result = Lists.newArrayListWithCapacity(refs.size());

    for (Ref ref : refs) {
      String name = ref.getName().substring(prefix.length());
      boolean needPrefix = !ref.getName().equals(refdb.getRef(name).getName());
      Map<String, Object> value = Maps.newHashMapWithExpectedSize(3);
      value.put("url", GitilesView.revision().copyFrom(view).setRevision(
        Revision.unpeeled(needPrefix ? ref.getName() : name, ref.getObjectId())).toUrl());
      value.put("name", name);
      if (headLeaf != null) {
        value.put("isHead", headLeaf.equals(ref));
      }
      result.add(value);
    }
    return result;
  }

  static String sanitizeRefForText(String refName) {
    return refName.replace("&", "&amp;")
        .replace("<", "&lt;")
        .replace(">", "&gt;");
  }

  private static Map<String, Ref> getRefs(RefDatabase refdb, String path) throws IOException {
    path = GitilesView.maybeTrimLeadingAndTrailingSlash(path);
    if (path.isEmpty()) {
      return refdb.getRefs(RefDatabase.ALL);
    }
    path = Constants.R_REFS + path;
    Ref singleRef = refdb.getRef(path);
    if (singleRef != null) {
      return ImmutableMap.of(singleRef.getName(), singleRef);
    }
    return refdb.getRefs(path + '/');
  }

  private static class TextRefAdvertiser extends RefAdvertiser {
    private final Writer writer;

    private TextRefAdvertiser(Writer writer) {
      this.writer = writer;
    }

    @Override
    public void advertiseId(AnyObjectId id, String refName) throws IOException {
      super.advertiseId(id, sanitizeRefForText(refName));
    }

    @Override
    protected void writeOne(CharSequence line) throws IOException {
      writer.append(line);
    }

    @Override
    public void end() throws IOException {
      writer.close();
    }
  }

  static class RefJsonData {
    RefJsonData(Ref ref) {
      value = ref.getObjectId().getName();
      if(ref.getPeeledObjectId() != null) {
        peeled = ref.getPeeledObjectId().getName();
      }
      if (ref.isSymbolic()) {
        target = ref.getTarget().getName();
      }
    }

    String value;
    String peeled;
    String target;
  }
}
