// 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.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.Objects.hash;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import java.io.IOException;
import java.util.Objects;
import org.eclipse.jgit.errors.AmbiguousObjectException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.RevisionSyntaxException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;

/** Object to parse revisions out of Gitiles paths. */
class RevisionParser {
  private static final Splitter OPERATOR_SPLITTER = Splitter.on(CharMatcher.anyOf("^~"));

  static class Result {
    private final Revision revision;
    private final Revision oldRevision;
    private final String path;

    @VisibleForTesting
    Result(Revision revision) {
      this(revision, null, "");
    }

    @VisibleForTesting
    Result(Revision revision, Revision oldRevision, String path) {
      this.revision = revision;
      this.oldRevision = oldRevision;
      this.path = path;
    }

    public Revision getRevision() {
      return revision;
    }

    public Revision getOldRevision() {
      return oldRevision;
    }

    public String getPath() {
      return path;
    }

    @Override
    public boolean equals(Object o) {
      if (o instanceof Result) {
        Result r = (Result) o;
        return Objects.equals(revision, r.revision)
            && Objects.equals(oldRevision, r.oldRevision)
            && Objects.equals(path, r.path);
      }
      return false;
    }

    @Override
    public int hashCode() {
      return hash(revision, oldRevision, path);
    }

    @Override
    public String toString() {
      return toStringHelper(this)
          .omitNullValues()
          .add("revision", revision.getName())
          .add("oldRevision", oldRevision != null ? oldRevision.getName() : null)
          .add("path", path)
          .toString();
    }
  }

  private final Repository repo;
  private final GitilesAccess access;
  private final VisibilityCache cache;

  RevisionParser(Repository repo, GitilesAccess access, VisibilityCache cache) {
    this.repo = checkNotNull(repo, "repo");
    this.access = checkNotNull(access, "access");
    this.cache = checkNotNull(cache, "cache");
  }

  Result parse(String path) throws IOException {
    if (path.startsWith("/")) {
      path = path.substring(1);
    }
    try (RevWalk walk = new RevWalk(repo)) {
      walk.setRetainBody(false);

      Revision oldRevision = null;

      StringBuilder b = new StringBuilder();
      boolean first = true;
      for (String part : PathUtil.SPLITTER.split(path)) {
        if (part.isEmpty()) {
          return null; // No valid revision contains empty segments.
        }
        if (!first) {
          b.append('/');
        }

        if (oldRevision == null) {
          int dots = part.indexOf("..");
          int firstParent = part.indexOf("^!");
          if (dots == 0 || firstParent == 0) {
            return null;
          } else if (dots > 0) {
            b.append(part, 0, dots);
            String oldName = b.toString();
            if (!isValidRevision(oldName)) {
              return null;
            }
            RevObject old = resolve(oldName, walk);
            if (old == null) {
              return null;
            }
            oldRevision = Revision.peel(oldName, old, walk);
            part = part.substring(dots + 2);
            b = new StringBuilder();
          } else if (firstParent > 0) {
            if (firstParent != part.length() - 2) {
              return null;
            }
            b.append(part, 0, part.length() - 2);
            String name = b.toString();
            if (!isValidRevision(name)) {
              return null;
            }
            RevObject obj = resolve(name, walk);
            if (obj == null) {
              return null;
            }
            while (obj instanceof RevTag) {
              obj = ((RevTag) obj).getObject();
              walk.parseHeaders(obj);
            }
            if (!(obj instanceof RevCommit)) {
              return null; // Not a commit, ^! is invalid.
            }
            RevCommit c = (RevCommit) obj;
            if (c.getParentCount() > 0) {
              oldRevision = Revision.peeled(name + "^", c.getParent(0));
            } else {
              oldRevision = Revision.NULL;
            }
            Result result =
                new Result(
                    Revision.peeled(name, c), oldRevision, path.substring(name.length() + 2));
            return isVisible(walk, result) ? result : null;
          }
        }
        b.append(part);

        String name = b.toString();
        if (!isValidRevision(name)) {
          return null;
        }
        RevObject obj = resolve(name, walk);
        if (obj != null) {
          int pathStart;
          if (oldRevision == null) {
            pathStart = name.length(); // foo
          } else {
            // foo..bar (foo may be empty)
            pathStart = oldRevision.getName().length() + 2 + name.length();
          }
          Result result =
              new Result(Revision.peel(name, obj, walk), oldRevision, path.substring(pathStart));
          return isVisible(walk, result) ? result : null;
        }
        first = false;
      }
      return null;
    }
  }

  private RevObject resolve(String name, RevWalk walk) throws IOException {
    try {
      ObjectId id = repo.resolve(name);
      return id != null ? walk.parseAny(id) : null;
    } catch (AmbiguousObjectException e) {
      // TODO(dborowitz): Render a helpful disambiguation page.
      return null;
    } catch (RevisionSyntaxException | MissingObjectException e) {
      return null;
    }
  }

  private static boolean isValidRevision(String revision) {
    // Disallow some uncommon but valid revision expressions that either we
    // don't support or we represent differently in our URLs.
    return !revision.contains(":") && !revision.contains("^{") && !revision.contains("@");
  }

  private boolean isVisible(RevWalk walk, Result result) throws IOException {
    String maybeRef = OPERATOR_SPLITTER.split(result.getRevision().getName()).iterator().next();
    if (repo.findRef(maybeRef) != null) {
      // Name contains a visible ref; skip expensive reachability check.
      return true;
    }
    ObjectId id = result.getRevision().getId();
    if (!cache.isVisible(repo, walk, access, id)) {
      return false;
    }
    if (result.getOldRevision() != null && result.getOldRevision() != Revision.NULL) {
      return cache.isVisible(repo, walk, access, result.getOldRevision().getId(), id);
    }
    return true;
  }
}
