// Copyright 2013 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 javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;

import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.gson.reflect.TypeToken;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.NameRevCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.errors.AmbiguousObjectException;
import org.eclipse.jgit.errors.RevisionSyntaxException;
import org.eclipse.jgit.http.server.ServletUtils;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;

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

/** Serves an API result describing an object. */
public class DescribeServlet extends BaseServlet {
  private static final long serialVersionUID = 1L;

  private static final String ALL_PARAM = "all";
  private static final String CONTAINS_PARAM = "contains";
  private static final String TAGS_PARAM = "tags";

  private static boolean getBooleanParam(GitilesView view, String name) {
    List<String> values = view.getParameters().get(name);
    return !values.isEmpty()
        && (values.get(0).equals("") || values.get(0).equals("1"));
  }

  protected DescribeServlet(GitilesAccess.Factory accessFactory) {
    super(null, accessFactory);
  }

  @Override
  protected void doGetText(HttpServletRequest req, HttpServletResponse res)
      throws IOException {
    String name = describe(ServletUtils.getRepository(req), ViewFilter.getView(req), req, res);
    if (name == null) {
      return;
    }
    PrintWriter out = startRenderText(req, res);
    out.write(RefServlet.sanitizeRefForText(name));
    out.close();
  }

  @Override
  protected void doGetJson(HttpServletRequest req, HttpServletResponse res)
      throws IOException {
    String name = describe(ServletUtils.getRepository(req), ViewFilter.getView(req), req, res);
    if (name == null) {
      return;
    }
    renderJson(req, res,
        ImmutableMap.of(ViewFilter.getView(req).getPathPart(), name),
        new TypeToken<Map<String, String>>() {}.getType());
  }

  private ObjectId resolve(Repository repo, GitilesView view, HttpServletRequest req,
      HttpServletResponse res) throws IOException {
    String rev = view.getPathPart();
    try {
      return repo.resolve(rev);
    } catch (RevisionSyntaxException e) {
      renderTextError(req, res, SC_BAD_REQUEST,
          "Invalid revision syntax: " + RefServlet.sanitizeRefForText(rev));
      return null;
    } catch (AmbiguousObjectException e) {
      renderTextError(req, res, SC_BAD_REQUEST, String.format(
            "Ambiguous short SHA-1 %s (%s)",
            e.getAbbreviatedObjectId(), Joiner.on(", ").join(e.getCandidates())));
      return null;
    }
  }

  private String describe(Repository repo, GitilesView view, HttpServletRequest req,
      HttpServletResponse res) throws IOException {
    if (!getBooleanParam(view, CONTAINS_PARAM)) {
      res.setStatus(SC_BAD_REQUEST);
      return null;
    }
    ObjectId id = resolve(repo, view, req, res);
    if (id == null) {
      return null;
    }
    NameRevCommand cmd = nameRevCommand(id, req, res);
    if (cmd == null) {
      return null;
    }
    String name;
    try {
      name = cmd.call().get(id);
    } catch (GitAPIException e) {
      throw new IOException(e);
    }
    if (name == null) {
      res.setStatus(SC_NOT_FOUND);
      return null;
    }
    return name;
  }

  private NameRevCommand nameRevCommand(ObjectId id, HttpServletRequest req,
      HttpServletResponse res) throws IOException {
    Repository repo = ServletUtils.getRepository(req);
    GitilesView view = ViewFilter.getView(req);
    NameRevCommand cmd = new Git(repo).nameRev();
    boolean all = getBooleanParam(view, ALL_PARAM);
    boolean tags = getBooleanParam(view, TAGS_PARAM);
    if (all && tags) {
      renderTextError(req, res, SC_BAD_REQUEST, "Cannot specify both \"all\" and \"tags\"");
      return null;
    }
    if (all) {
      cmd.addPrefix(Constants.R_REFS);
    } else if (tags) {
      cmd.addPrefix(Constants.R_TAGS);
    } else {
      cmd.addAnnotatedTags();
    }
    cmd.add(id);
    return cmd;
  }
}
