// Copyright (C) 2014 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.client.diff;

import com.google.gerrit.client.DiffObject;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.changes.CommentInfo;
import com.google.gerrit.client.patches.SkippedLine;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.ui.CommentLinkProcessor;
import com.google.gerrit.extensions.client.Side;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.JsArray;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import net.codemirror.lib.CodeMirror;
import net.codemirror.lib.Pos;
import net.codemirror.lib.TextMarker.FromTo;

/** Tracks comment widgets for {@link DiffScreen}. */
abstract class CommentManager {
  private final DiffObject base;
  private final PatchSet.Id revision;
  private final String path;
  private final CommentLinkProcessor commentLinkProcessor;
  final SortedMap<Integer, CommentGroup> sideA;
  final SortedMap<Integer, CommentGroup> sideB;
  private final Map<String, PublishedBox> published;
  private final Set<DraftBox> unsavedDrafts;
  final DiffScreen host;
  private boolean attached;
  private boolean expandAll;
  private boolean open;

  CommentManager(
      DiffScreen host,
      DiffObject base,
      PatchSet.Id revision,
      String path,
      CommentLinkProcessor clp,
      boolean open) {
    this.host = host;
    this.base = base;
    this.revision = revision;
    this.path = path;
    this.commentLinkProcessor = clp;
    this.open = open;

    published = new HashMap<>();
    unsavedDrafts = new HashSet<>();
    sideA = new TreeMap<>();
    sideB = new TreeMap<>();
  }

  void setAttached(boolean attached) {
    this.attached = attached;
  }

  boolean isAttached() {
    return attached;
  }

  void setExpandAll(boolean expandAll) {
    this.expandAll = expandAll;
  }

  boolean isExpandAll() {
    return expandAll;
  }

  boolean isOpen() {
    return open;
  }

  String getPath() {
    return path;
  }

  Map<String, PublishedBox> getPublished() {
    return published;
  }

  CommentLinkProcessor getCommentLinkProcessor() {
    return commentLinkProcessor;
  }

  void renderDrafts(DisplaySide forSide, JsArray<CommentInfo> in) {
    for (CommentInfo info : Natives.asList(in)) {
      DisplaySide side = displaySide(info, forSide);
      if (side != null) {
        addDraftBox(side, info);
      }
    }
  }

  void setUnsaved(DraftBox box, boolean isUnsaved) {
    if (isUnsaved) {
      unsavedDrafts.add(box);
    } else {
      unsavedDrafts.remove(box);
    }
  }

  void saveAllDrafts(CallbackGroup cb) {
    for (DraftBox box : unsavedDrafts) {
      box.save(cb);
    }
  }

  Side getStoredSideFromDisplaySide(DisplaySide side) {
    if (side == DisplaySide.A && (base.isBaseOrAutoMerge() || base.isParent())) {
      return Side.PARENT;
    }
    return Side.REVISION;
  }

  int getParentNumFromDisplaySide(DisplaySide side) {
    if (side == DisplaySide.A) {
      return base.getParentNum();
    }
    return 0;
  }

  PatchSet.Id getPatchSetIdFromSide(DisplaySide side) {
    if (side == DisplaySide.A && (base.isPatchSet() || base.isEdit())) {
      return base.asPatchSetId();
    }
    return revision;
  }

  DisplaySide displaySide(CommentInfo info, DisplaySide forSide) {
    if (info.side() == Side.PARENT) {
      return (base.isBaseOrAutoMerge() || base.isParent()) ? DisplaySide.A : null;
    }
    return forSide;
  }

  static FromTo adjustSelection(CodeMirror cm) {
    FromTo fromTo = cm.getSelectedRange();
    Pos to = fromTo.to();
    if (to.ch() == 0) {
      to.line(to.line() - 1);
      to.ch(cm.getLine(to.line()).length());
    }
    return fromTo;
  }

  abstract CommentGroup group(DisplaySide side, int cmLinePlusOne);

  /**
   * Create a new {@link DraftBox} at the specified line and focus it.
   *
   * @param side which side the draft will appear on.
   * @param line the line the draft will be at. Lines are 1-based. Line 0 is a special case creating
   *     a file level comment.
   */
  void insertNewDraft(DisplaySide side, int line) {
    if (line == 0) {
      host.skipManager.ensureFirstLineIsVisible();
    }

    CommentGroup group = group(side, line);
    if (0 < group.getBoxCount()) {
      CommentBox last = group.getCommentBox(group.getBoxCount() - 1);
      if (last instanceof DraftBox) {
        ((DraftBox) last).setEdit(true);
      } else {
        ((PublishedBox) last).doReply();
      }
    } else {
      addDraftBox(
              side,
              CommentInfo.create(
                  getPath(),
                  getStoredSideFromDisplaySide(side),
                  getParentNumFromDisplaySide(side),
                  line,
                  null,
                  false))
          .setEdit(true);
    }
  }

  abstract String getTokenSuffixForActiveLine(CodeMirror cm);

  Runnable signInCallback(CodeMirror cm) {
    return () -> {
      String token = host.getToken();
      if (cm.extras().hasActiveLine()) {
        token += "@" + getTokenSuffixForActiveLine(cm);
      }
      Gerrit.doSignIn(token);
    };
  }

  abstract void newDraft(CodeMirror cm);

  Runnable newDraftCallback(CodeMirror cm) {
    if (!Gerrit.isSignedIn()) {
      return signInCallback(cm);
    }

    return () -> {
      if (cm.extras().hasActiveLine()) {
        newDraft(cm);
      }
    };
  }

  DraftBox addDraftBox(DisplaySide side, CommentInfo info) {
    int cmLinePlusOne = host.getCmLine(info.line() - 1, side) + 1;
    CommentGroup group = group(side, cmLinePlusOne);
    DraftBox box =
        new DraftBox(
            group, getCommentLinkProcessor(), getPatchSetIdFromSide(side), info, isExpandAll());

    if (info.inReplyTo() != null) {
      PublishedBox r = getPublished().get(info.inReplyTo());
      if (r != null) {
        r.setReplyBox(box);
      }
    }

    group.add(box);
    box.setAnnotation(
        host.getDiffTable()
            .scrollbar
            .draft(host.getCmFromSide(side), Math.max(0, cmLinePlusOne - 1)));
    return box;
  }

  void setExpandAllComments(boolean b) {
    setExpandAll(b);
    for (CommentGroup g : sideA.values()) {
      g.setOpenAll(b);
    }
    for (CommentGroup g : sideB.values()) {
      g.setOpenAll(b);
    }
  }

  abstract SortedMap<Integer, CommentGroup> getMapForNav(DisplaySide side);

  Runnable commentNav(final CodeMirror src, final Direction dir) {
    return () -> {
      // Every comment appears in both side maps as a linked pair.
      // It is only necessary to search one side to find a comment
      // on either side of the editor pair.
      SortedMap<Integer, CommentGroup> map = getMapForNav(src.side());
      int line =
          src.extras().hasActiveLine() ? src.getLineNumber(src.extras().activeLine()) + 1 : 0;

      CommentGroup g;
      if (dir == Direction.NEXT) {
        map = map.tailMap(line + 1);
        if (map.isEmpty()) {
          return;
        }
        g = map.get(map.firstKey());
        while (g.getBoxCount() == 0) {
          map = map.tailMap(map.firstKey() + 1);
          if (map.isEmpty()) {
            return;
          }
          g = map.get(map.firstKey());
        }
      } else {
        map = map.headMap(line);
        if (map.isEmpty()) {
          return;
        }
        g = map.get(map.lastKey());
        while (g.getBoxCount() == 0) {
          map = map.headMap(map.lastKey());
          if (map.isEmpty()) {
            return;
          }
          g = map.get(map.lastKey());
        }
      }

      CodeMirror cm = g.getCm();
      double y = cm.heightAtLine(g.getLine() - 1, "local");
      cm.setCursor(Pos.create(g.getLine() - 1));
      cm.scrollToY(y - 0.5 * cm.scrollbarV().getClientHeight());
      cm.focus();
    };
  }

  void clearLine(DisplaySide side, int line, CommentGroup group) {
    SortedMap<Integer, CommentGroup> map = map(side);
    if (map.get(line) == group) {
      map.remove(line);
    }
  }

  void render(CommentsCollections in, boolean expandAll) {
    if (in.publishedBase != null) {
      renderPublished(DisplaySide.A, in.publishedBase);
    }
    if (in.publishedRevision != null) {
      renderPublished(DisplaySide.B, in.publishedRevision);
    }
    if (in.draftsBase != null) {
      renderDrafts(DisplaySide.A, in.draftsBase);
    }
    if (in.draftsRevision != null) {
      renderDrafts(DisplaySide.B, in.draftsRevision);
    }
    if (expandAll) {
      setExpandAllComments(true);
    }
    for (CommentGroup g : sideA.values()) {
      g.init(host.getDiffTable());
    }
    for (CommentGroup g : sideB.values()) {
      g.init(host.getDiffTable());
      g.handleRedraw();
    }
    setAttached(true);
  }

  void renderPublished(DisplaySide forSide, JsArray<CommentInfo> in) {
    for (CommentInfo info : Natives.asList(in)) {
      DisplaySide side = displaySide(info, forSide);
      if (side != null) {
        int cmLinePlusOne = host.getCmLine(info.line() - 1, side) + 1;
        CommentGroup group = group(side, cmLinePlusOne);
        PublishedBox box =
            new PublishedBox(
                group,
                getCommentLinkProcessor(),
                getPatchSetIdFromSide(side),
                info,
                side,
                isOpen());
        group.add(box);
        box.setAnnotation(
            host.getDiffTable().scrollbar.comment(host.getCmFromSide(side), cmLinePlusOne - 1));
        getPublished().put(info.id(), box);
      }
    }
  }

  abstract Collection<Integer> getLinesWithCommentGroups();

  private static void checkAndAddSkip(List<SkippedLine> out, SkippedLine s) {
    if (s.getSize() > 1) {
      out.add(s);
    }
  }

  List<SkippedLine> splitSkips(int context, List<SkippedLine> skips) {
    if (sideA.containsKey(0) || sideB.containsKey(0)) {
      // Special case of file comment; cannot skip first line.
      for (SkippedLine skip : skips) {
        if (skip.getStartA() == 0) {
          skip.incrementStart(1);
          break;
        }
      }
    }

    for (int boxLine : getLinesWithCommentGroups()) {
      List<SkippedLine> temp = new ArrayList<>(skips.size() + 2);
      for (SkippedLine skip : skips) {
        int startLine = host.getCmLine(skip.getStartB(), DisplaySide.B);
        int deltaBefore = boxLine - startLine;
        int deltaAfter = startLine + skip.getSize() - boxLine;
        if (deltaBefore < -context || deltaAfter < -context) {
          temp.add(skip); // Size guaranteed to be greater than 1
        } else if (deltaBefore > context && deltaAfter > context) {
          SkippedLine before =
              new SkippedLine(
                  skip.getStartA(), skip.getStartB(), skip.getSize() - deltaAfter - context);
          skip.incrementStart(deltaBefore + context);
          checkAndAddSkip(temp, before);
          checkAndAddSkip(temp, skip);
        } else if (deltaAfter > context) {
          skip.incrementStart(deltaBefore + context);
          checkAndAddSkip(temp, skip);
        } else if (deltaBefore > context) {
          skip.reduceSize(deltaAfter + context);
          checkAndAddSkip(temp, skip);
        }
      }
      if (temp.isEmpty()) {
        return temp;
      }
      skips = temp;
    }
    return skips;
  }

  abstract void newDraftOnGutterClick(CodeMirror cm, String gutterClass, int line);

  abstract CommentGroup getCommentGroupOnActiveLine(CodeMirror cm);

  Runnable toggleOpenBox(CodeMirror cm) {
    return () -> {
      CommentGroup group = getCommentGroupOnActiveLine(cm);
      if (group != null) {
        group.openCloseLast();
      }
    };
  }

  Runnable openCloseAll(CodeMirror cm) {
    return () -> {
      CommentGroup group = getCommentGroupOnActiveLine(cm);
      if (group != null) {
        group.openCloseAll();
      }
    };
  }

  SortedMap<Integer, CommentGroup> map(DisplaySide side) {
    return side == DisplaySide.A ? sideA : sideB;
  }
}
