// 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.common.data;

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

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CommentDetail {
  protected List<PatchLineComment> a;
  protected List<PatchLineComment> b;
  protected AccountInfoCache accounts;

  private transient PatchSet.Id idA;
  private transient PatchSet.Id idB;
  private transient Map<Integer, List<PatchLineComment>> forA;
  private transient Map<Integer, List<PatchLineComment>> forB;

  public CommentDetail(PatchSet.Id idA, PatchSet.Id idB) {
    this.a = new ArrayList<>();
    this.b = new ArrayList<>();
    this.idA = idA;
    this.idB = idB;
  }

  protected CommentDetail() {
  }

  public boolean include(final PatchLineComment p) {
    final PatchSet.Id psId = p.getKey().getParentKey().getParentKey();
    switch (p.getSide()) {
      case 0:
        if (idA == null && idB.equals(psId)) {
          a.add(p);
          return true;
        }
        break;

      case 1:
        if (idA != null && idA.equals(psId)) {
          a.add(p);
          return true;
        }

        if (idB.equals(psId)) {
          b.add(p);
          return true;
        }
        break;
    }
    return false;
  }

  public void setAccountInfoCache(final AccountInfoCache a) {
    accounts = a;
  }

  public AccountInfoCache getAccounts() {
    return accounts;
  }

  public List<PatchLineComment> getCommentsA() {
    return a;
  }

  public List<PatchLineComment> getCommentsB() {
    return b;
  }

  public boolean isEmpty() {
    return a.isEmpty() && b.isEmpty();
  }

  public List<PatchLineComment> getForA(final int lineNbr) {
    if (forA == null) {
      forA = index(a);
    }
    return get(forA, lineNbr);
  }

  public List<PatchLineComment> getForB(final int lineNbr) {
    if (forB == null) {
      forB = index(b);
    }
    return get(forB, lineNbr);
  }

  private static List<PatchLineComment> get(
      final Map<Integer, List<PatchLineComment>> m, final int i) {
    final List<PatchLineComment> r = m.get(i);
    return r != null ? orderComments(r) : Collections.<PatchLineComment> emptyList();
  }

  /**
   * Order the comments based on their parent_uuid parent.  It is possible to do this by
   * iterating over the list only once but it's probably overkill since the number of comments
   * on a given line will be small most of the time.
   *
   * @param comments The list of comments for a given line.
   * @return The comments sorted as they should appear in the UI
   */
  private static List<PatchLineComment> orderComments(List<PatchLineComment> comments) {
    // Map of comments keyed by their parent. The values are lists of comments since it is
    // possible for several comments to have the same parent (this can happen if two reviewers
    // click Reply on the same comment at the same time). Such comments will be displayed under
    // their correct parent in chronological order.
    Map<String, List<PatchLineComment>> parentMap = new HashMap<>();

    // It's possible to have more than one root comment if two reviewers create a comment on the
    // same line at the same time
    List<PatchLineComment> rootComments = new ArrayList<>();

    // Store all the comments in parentMap, keyed by their parent
    for (PatchLineComment c : comments) {
      String parentUuid = c.getParentUuid();
      List<PatchLineComment> l = parentMap.get(parentUuid);
      if (l == null) {
        l = new ArrayList<>();
        parentMap.put(parentUuid, l);
      }
      l.add(c);
      if (parentUuid == null) {
        rootComments.add(c);
      }
    }

    // Add the comments in the list, starting with the head and then going through all the
    // comments that have it as a parent, and so on
    List<PatchLineComment> result = new ArrayList<>();
    addChildren(parentMap, rootComments, result);

    return result;
  }

  /**
   * Add the comments to {@code outResult}, depth first
   */
  private static void addChildren(Map<String, List<PatchLineComment>> parentMap,
      List<PatchLineComment> children, List<PatchLineComment> outResult) {
    if (children != null) {
      for (PatchLineComment c : children) {
        outResult.add(c);
        addChildren(parentMap, parentMap.get(c.getKey().get()), outResult);
      }
    }
  }

  private Map<Integer, List<PatchLineComment>> index(
      List<PatchLineComment> in) {
    HashMap<Integer, List<PatchLineComment>> r = new HashMap<>();
    for (final PatchLineComment p : in) {
      List<PatchLineComment> l = r.get(p.getLine());
      if (l == null) {
        l = new ArrayList<>();
        r.put(p.getLine(), l);
      }
      l.add(p);
    }
    return r;
  }
}
