// Copyright (C) 2013 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.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.common.changes.Side;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.JsArray;

import net.codemirror.lib.CodeMirror;
import net.codemirror.lib.CodeMirror.LineHandle;
import net.codemirror.lib.LineCharacter;
import net.codemirror.lib.TextMarker.FromTo;

import java.util.ArrayList;
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;

/** Tracks comment widgets for {@link SideBySide2}. */
class CommentManager {
  private final SideBySide2 host;
  private final PatchSet.Id base;
  private final PatchSet.Id revision;
  private final String path;
  private final CommentLinkProcessor commentLinkProcessor;

  private final Map<String, PublishedBox> published;
  private final SortedMap<Integer, CommentGroup> sideA;
  private final SortedMap<Integer, CommentGroup> sideB;
  private final Set<DraftBox> unsavedDrafts;
  private boolean attached;

  CommentManager(SideBySide2 host,
      PatchSet.Id base, PatchSet.Id revision,
      String path,
      CommentLinkProcessor clp) {
    this.host = host;
    this.base = base;
    this.revision = revision;
    this.path = path;
    this.commentLinkProcessor = clp;

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

  SideBySide2 getSideBySide2() {
    return host;
  }

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

  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 = map(src.side());
        int line = src.hasActiveLine()
            ? src.getLineNumber(src.getActiveLine()) + 1
            : 0;
        if (dir == Direction.NEXT) {
          map = map.tailMap(line + 1);
          if (map.isEmpty()) {
            return;
          }
          line = map.firstKey();
        } else {
          map = map.headMap(line);
          if (map.isEmpty()) {
            return;
          }
          line = map.lastKey();
        }

        CommentGroup g = map.get(line);
        if (g.getBoxCount() == 0) {
          g = g.getPeer();
        }

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

  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.attachPair(host.diffTable);
    }
    for (CommentGroup g : sideB.values()) {
      g.attachPair(host.diffTable);
      g.handleRedraw();
    }
    attached = true;
  }

  private void renderPublished(DisplaySide forSide, JsArray<CommentInfo> in) {
    for (CommentInfo info : Natives.asList(in)) {
      DisplaySide side = displaySide(info, forSide);
      if (side != null) {
        CommentGroup group = group(side, info.line());
        PublishedBox box = new PublishedBox(
            group,
            commentLinkProcessor,
            getPatchSetIdFromSide(side),
            info);
        group.add(box);
        box.setMark(host.diffTable.overview.add(
            host.getCmFromSide(side),
            Math.max(0, info.line() - 1), 1,
            OverviewBar.MarkType.COMMENT));
        published.put(info.id(), box);
      }
    }
  }

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

  /**
   * 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.getSkipManager().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(
          path,
          getStoredSideFromDisplaySide(side),
          line,
          null)).setEdit(true);
    }
  }

  DraftBox addDraftBox(DisplaySide side, CommentInfo info) {
    CommentGroup group = group(side, info.line());
    DraftBox box = new DraftBox(
        group,
        commentLinkProcessor,
        getPatchSetIdFromSide(side),
        info);

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

    group.add(box);
    box.setMark(host.diffTable.overview.add(
        host.getCmFromSide(side),
        Math.max(0, info.line() - 1), 1,
        OverviewBar.MarkType.DRAFT));
    return box;
  }

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

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

    // TODO: This is not optimal, but shouldn't be too costly in most cases.
    // Maybe rewrite after done keeping track of diff chunk positions.
    for (int boxLine : sideB.tailMap(1).keySet()) {
      List<SkippedLine> temp = new ArrayList<>(skips.size() + 2);
      for (SkippedLine skip : skips) {
        int startLine = skip.getStartB();
        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;
  }

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

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

  Runnable toggleOpenBox(final CodeMirror cm) {
    return new Runnable() {
      public void run() {
        if (cm.hasActiveLine()) {
          CommentGroup w = map(cm.side()).get(
              cm.getLineNumber(cm.getActiveLine()) + 1);
          if (w != null) {
            w.openCloseLast();
          }
        }
      }
    };
  }

  Runnable openCloseAll(final CodeMirror cm) {
    return new Runnable() {
      @Override
      public void run() {
        if (cm.hasActiveLine()) {
          CommentGroup w = map(cm.side()).get(
              cm.getLineNumber(cm.getActiveLine()) + 1);
          if (w != null) {
            w.openCloseAll();
          }
        }
      }
    };
  }

  Runnable insertNewDraft(final CodeMirror cm) {
    if (!Gerrit.isSignedIn()) {
      return new Runnable() {
        @Override
        public void run() {
          String token = host.getToken();
          if (cm.hasActiveLine()) {
            LineHandle handle = cm.getActiveLine();
            int line = cm.getLineNumber(handle) + 1;
            token += "@" + (cm.side() == DisplaySide.A ? "a" : "") + line;
          }
          Gerrit.doSignIn(token);
        }
     };
    }

    return new Runnable() {
      public void run() {
        if (cm.hasActiveLine()) {
          newDraft(cm);
        }
      }
    };
  }

  private void newDraft(CodeMirror cm) {
    int line = cm.getLineNumber(cm.getActiveLine()) + 1;
    if (cm.somethingSelected()) {
      FromTo fromTo = cm.getSelectedRange();
      LineCharacter end = fromTo.getTo();
      if (end.getCh() == 0) {
        end.setLine(end.getLine() - 1);
        end.setCh(cm.getLine(end.getLine()).length());
      }

      addDraftBox(cm.side(), CommentInfo.create(
              path,
              getStoredSideFromDisplaySide(cm.side()),
              line,
              CommentRange.create(fromTo))).setEdit(true);
      cm.setSelection(cm.getCursor());
    } else {
      insertNewDraft(cm.side(), line);
    }
  }

  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);
    }
  }

  private CommentGroup group(DisplaySide side, int line) {
    CommentGroup w = map(side).get(line);
    if (w != null) {
      return w;
    }

    int lineA, lineB;
    if (line == 0) {
      lineA = lineB = 0;
    } else if (side == DisplaySide.A) {
      lineA = line;
      lineB = host.lineOnOther(side, line - 1).getLine() + 1;
    } else {
      lineA = host.lineOnOther(side, line - 1).getLine() + 1;
      lineB = line;
    }

    CommentGroup a = newGroup(DisplaySide.A, lineA);
    CommentGroup b = newGroup(DisplaySide.B, lineB);
    CommentGroup.pair(a, b);

    sideA.put(lineA, a);
    sideB.put(lineB, b);

    if (attached) {
      a.attachPair(host.diffTable);
      b.handleRedraw();
    }

    return side == DisplaySide.A ? a : b;
  }

  private CommentGroup newGroup(DisplaySide side, int line) {
    return new CommentGroup(this, host.getCmFromSide(side), line);
  }

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

  private Side getStoredSideFromDisplaySide(DisplaySide side) {
    return side == DisplaySide.A && base == null ? Side.PARENT : Side.REVISION;
  }

  private PatchSet.Id getPatchSetIdFromSide(DisplaySide side) {
    return side == DisplaySide.A && base != null ? base : revision;
  }
}
