// Copyright (C) 2016 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.notedb;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_ATTENTION;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_PATCH_SET;

import com.google.common.collect.ListMultimap;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.Sets;
import com.google.gerrit.server.git.InMemoryInserter;
import com.google.gerrit.server.git.InsertedObject;
import java.io.IOException;
import java.util.List;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.FooterKey;
import org.eclipse.jgit.revwalk.FooterLine;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

/**
 * Commit implementation with some optimizations for change notes parsing.
 *
 * <p>
 *
 * <ul>
 *   <li>Caches the result of {@link #getFooterLines()}, which is otherwise very wasteful with
 *       allocations.
 * </ul>
 */
public class ChangeNotesCommit extends RevCommit {

  /** A {@link RevWalk} producing {@link ChangeNotesCommit}s. */
  public static ChangeNotesRevWalk newRevWalk(Repository repo) {
    return new ChangeNotesRevWalk(repo);
  }

  public static ChangeNotesRevWalk newStagedRevWalk(
      Repository repo, Iterable<InsertedObject> stagedObjs) {
    final InMemoryInserter ins = new InMemoryInserter(repo);
    for (InsertedObject obj : stagedObjs) {
      ins.insert(obj);
    }
    return new ChangeNotesRevWalk(ins.newReader()) {
      @Override
      public void close() {
        ins.close();
        super.close();
      }
    };
  }

  /** A {@link RevWalk} that creates {@link ChangeNotesCommit}s rather than {@link RevCommit}s */
  public static class ChangeNotesRevWalk extends RevWalk {
    private ChangeNotesRevWalk(Repository repo) {
      super(repo);
    }

    private ChangeNotesRevWalk(ObjectReader reader) {
      super(reader);
    }

    @Override
    protected ChangeNotesCommit createCommit(AnyObjectId id) {
      return new ChangeNotesCommit(id);
    }

    @Override
    public ChangeNotesCommit next()
        throws MissingObjectException, IncorrectObjectTypeException, IOException {
      return (ChangeNotesCommit) super.next();
    }

    @Override
    public void markStart(RevCommit c)
        throws MissingObjectException, IncorrectObjectTypeException, IOException {
      checkArgument(c instanceof ChangeNotesCommit);
      super.markStart(c);
    }

    @Override
    public void markUninteresting(RevCommit c)
        throws MissingObjectException, IncorrectObjectTypeException, IOException {
      checkArgument(c instanceof ChangeNotesCommit);
      super.markUninteresting(c);
    }

    @Override
    public ChangeNotesCommit lookupCommit(AnyObjectId id) {
      return (ChangeNotesCommit) super.lookupCommit(id);
    }

    @Override
    public ChangeNotesCommit parseCommit(AnyObjectId id)
        throws MissingObjectException, IncorrectObjectTypeException, IOException {
      return (ChangeNotesCommit) super.parseCommit(id);
    }
  }

  private ListMultimap<String, String> footerLines;

  public ChangeNotesCommit(AnyObjectId id) {
    super(id);
  }

  public List<String> getFooterLineValues(FooterKey key) {
    if (footerLines == null) {
      List<FooterLine> src = getFooterLines();
      footerLines = MultimapBuilder.hashKeys(src.size()).arrayListValues(1).build();
      for (FooterLine fl : src) {
        footerLines.put(fl.getKey().toLowerCase(), fl.getValue());
      }
    }
    return footerLines.get(key.getName().toLowerCase());
  }

  public boolean isAttentionSetCommitOnly(boolean hasChangeMessage) {
    return !hasChangeMessage
        && footerLines
            .keySet()
            .equals(
                Sets.newHashSet(
                    FOOTER_PATCH_SET.getName().toLowerCase(),
                    FOOTER_ATTENTION.getName().toLowerCase()));
  }
}
