// 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(final CodeMirror cm) {
    return new Runnable() {
      @Override
      public void run() {
        String token = host.getToken();
        if (cm.extras().hasActiveLine()) {
          token += "@" + getTokenSuffixForActiveLine(cm);
        }
        Gerrit.doSignIn(token);
      }
    };
  }

  abstract void newDraft(CodeMirror cm);

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

    return new Runnable() {
      @Override
      public void run() {
        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 new Runnable() {
      @Override
      public void run() {
        // 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(final CodeMirror cm) {
    return new Runnable() {
      @Override
      public void run() {
        CommentGroup group = getCommentGroupOnActiveLine(cm);
        if (group != null) {
          group.openCloseLast();
        }
      }
    };
  }

  Runnable openCloseAll(final CodeMirror cm) {
    return new Runnable() {
      @Override
      public void run() {
        CommentGroup group = getCommentGroupOnActiveLine(cm);
        if (group != null) {
          group.openCloseAll();
        }
      }
    };
  }

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