// 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(final PatchSet.Id idA, final PatchSet.Id idB) {
    this.a = new ArrayList<PatchLineComment>();
    this.b = new ArrayList<PatchLineComment>();
    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 (lineNbr == 0) {
      return Collections.emptyList();
    }
    if (forA == null) {
      forA = index(a);
    }
    return get(forA, lineNbr);
  }

  public List<PatchLineComment> getForB(final int lineNbr) {
    if (lineNbr == 0) {
      return Collections.emptyList();
    }
    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<String, List<PatchLineComment>>();

    // 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<PatchLineComment>();

    // 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<PatchLineComment>();
        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<PatchLineComment>();
    addChildren(parentMap, rootComments, result);

    return result;
  }

  /**
   * Add the comments to <code>outResult</code>, 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(
      final List<PatchLineComment> in) {
    final HashMap<Integer, List<PatchLineComment>> r;

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