// Copyright (C) 2009 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.patch;


import static com.google.gerrit.server.ioutil.BasicSerialization.readBytes;
import static com.google.gerrit.server.ioutil.BasicSerialization.readVarInt32;
import static com.google.gerrit.server.ioutil.BasicSerialization.writeBytes;
import static com.google.gerrit.server.ioutil.BasicSerialization.writeVarInt32;
import static org.eclipse.jgit.lib.ObjectIdSerialization.readCanBeNull;
import static org.eclipse.jgit.lib.ObjectIdSerialization.readNotNull;
import static org.eclipse.jgit.lib.ObjectIdSerialization.writeCanBeNull;
import static org.eclipse.jgit.lib.ObjectIdSerialization.writeNotNull;

import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchSet;

import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectId;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;

import javax.annotation.Nullable;

public class PatchList implements Serializable {
  private static final long serialVersionUID = PatchListKey.serialVersionUID;
  private static final Comparator<PatchListEntry> PATCH_CMP =
      new Comparator<PatchListEntry>() {
        @Override
        public int compare(final PatchListEntry a, final PatchListEntry b) {
          return a.getNewName().compareTo(b.getNewName());
        }
      };

  @Nullable
  private transient ObjectId oldId;
  private transient ObjectId newId;
  private transient boolean againstParent;
  private transient int insertions;
  private transient int deletions;
  private transient PatchListEntry[] patches;

  PatchList(@Nullable final AnyObjectId oldId, final AnyObjectId newId,
      final boolean againstParent, final PatchListEntry[] patches) {
    this.oldId = oldId != null ? oldId.copy() : null;
    this.newId = newId.copy();
    this.againstParent = againstParent;

    // We assume index 0 contains the magic commit message entry.
    if (patches.length > 1) {
      Arrays.sort(patches, 1, patches.length, PATCH_CMP);
    }
    for (int i = 1; i < patches.length; i++) {
      insertions += patches[i].getInsertions();
      deletions += patches[i].getDeletions();
    }

    this.patches = patches;
  }

  /** Old side tree or commit; null only if this is a combined diff. */
  @Nullable
  public ObjectId getOldId() {
    return oldId;
  }

  /** New side commit. */
  public ObjectId getNewId() {
    return newId;
  }

  /** Get a sorted, unmodifiable list of all files in this list. */
  public List<PatchListEntry> getPatches() {
    return Collections.unmodifiableList(Arrays.asList(patches));
  }

  /** @return true if {@link #getOldId} is {@link #getNewId}'s ancestor. */
  public boolean isAgainstParent() {
    return againstParent;
  }

  /** @return total number of new lines added. */
  public int getInsertions() {
    return insertions;
  }

  /** @return total number of lines removed. */
  public int getDeletions() {
    return deletions;
  }

  /**
   * Get a sorted, modifiable list of all files in this list.
   * <p>
   * The returned list items do not populate:
   * <ul>
   * <li>{@link Patch#getCommentCount()}
   * <li>{@link Patch#getDraftCount()}
   * <li>{@link Patch#isReviewedByCurrentUser()}
   * </ul>
   *
   * @param setId the patch set identity these patches belong to. This really
   *        should not need to be specified, but is a current legacy artifact of
   *        how the cache is keyed versus how the database is keyed.
   */
  public List<Patch> toPatchList(final PatchSet.Id setId) {
    final ArrayList<Patch> r = new ArrayList<Patch>(patches.length);
    for (final PatchListEntry e : patches) {
      r.add(e.toPatch(setId));
    }
    return r;
  }

  /** Find an entry by name, returning an empty entry if not present. */
  public PatchListEntry get(final String fileName) {
    final int index = search(fileName);
    return 0 <= index ? patches[index] : PatchListEntry.empty(fileName);
  }

  private int search(final String fileName) {
    if (Patch.COMMIT_MSG.equals(fileName)) {
      return 0;
    }

    int high = patches.length;
    int low = 1;
    while (low < high) {
      final int mid = (low + high) >>> 1;
      final int cmp = patches[mid].getNewName().compareTo(fileName);
      if (cmp < 0)
        low = mid + 1;
      else if (cmp == 0)
        return mid;
      else
        high = mid;
    }
    return -(low + 1);
  }

  private void writeObject(final ObjectOutputStream output) throws IOException {
    final ByteArrayOutputStream buf = new ByteArrayOutputStream();
    final DeflaterOutputStream out = new DeflaterOutputStream(buf);
    try {
      writeCanBeNull(out, oldId);
      writeNotNull(out, newId);
      writeVarInt32(out, againstParent ? 1 : 0);
      writeVarInt32(out, insertions);
      writeVarInt32(out, deletions);
      writeVarInt32(out, patches.length);
      for (PatchListEntry p : patches) {
        p.writeTo(out);
      }
    } finally {
      out.close();
    }
    writeBytes(output, buf.toByteArray());
  }

  private void readObject(final ObjectInputStream input) throws IOException {
    final ByteArrayInputStream buf = new ByteArrayInputStream(readBytes(input));
    final InflaterInputStream in = new InflaterInputStream(buf);
    try {
      oldId = readCanBeNull(in);
      newId = readNotNull(in);
      againstParent = readVarInt32(in) != 0;
      insertions = readVarInt32(in);
      deletions = readVarInt32(in);
      final int cnt = readVarInt32(in);
      final PatchListEntry[] all = new PatchListEntry[cnt];
      for (int i = 0; i < all.length; i++) {
        all[i] = PatchListEntry.readFrom(in);
      }
      patches = all;
    } finally {
      in.close();
    }
  }
}
