// 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.extensions.client.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.Pos;
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 SideBySide}. */
class CommentManager {
  private final SideBySide 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;
  private boolean expandAll;
  private boolean open;

  CommentManager(SideBySide host,
      PatchSet.Id 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<>();
    sideA = new TreeMap<>();
    sideB = new TreeMap<>();
    unsavedDrafts = new HashSet<>();
  }

  SideBySide getSideBySide() {
    return host;
  }

  void setExpandAllComments(boolean b) {
    expandAll = 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.extras().hasActiveLine()
            ? src.getLineNumber(src.extras().activeLine()) + 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(Pos.create(g.getLine() - 1));
        cm.scrollToY(y - 0.5 * cm.scrollbarV().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,
            open);
        group.add(box);
        box.setAnnotation(host.diffTable.scrollbar.comment(
            host.getCmFromSide(side),
            Math.max(0, info.line() - 1)));
        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,
        expandAll);

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

    group.add(box);
    box.setAnnotation(host.diffTable.scrollbar.draft(
        host.getCmFromSide(side),
        Math.max(0, info.line() - 1)));
    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() {
      @Override
      public void run() {
        if (cm.extras().hasActiveLine()) {
          CommentGroup w = map(cm.side()).get(
              cm.getLineNumber(cm.extras().activeLine()) + 1);
          if (w != null) {
            w.openCloseLast();
          }
        }
      }
    };
  }

  Runnable openCloseAll(final CodeMirror cm) {
    return new Runnable() {
      @Override
      public void run() {
        if (cm.extras().hasActiveLine()) {
          CommentGroup w = map(cm.side()).get(
              cm.getLineNumber(cm.extras().activeLine()) + 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.extras().hasActiveLine()) {
            LineHandle handle = cm.extras().activeLine();
            int line = cm.getLineNumber(handle) + 1;
            token += "@" + (cm.side() == DisplaySide.A ? "a" : "") + line;
          }
          Gerrit.doSignIn(token);
        }
     };
    }

    return new Runnable() {
      @Override
      public void run() {
        if (cm.extras().hasActiveLine()) {
          newDraft(cm, cm.getLineNumber(cm.extras().activeLine()) + 1);
        }
      }
    };
  }

  void newDraft(CodeMirror cm, int line) {
    if (cm.somethingSelected()) {
      FromTo fromTo = cm.getSelectedRange();
      Pos end = fromTo.to();
      if (end.ch() == 0) {
        end.line(end.line() - 1);
        end.ch(cm.getLine(end.line()).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;
    int 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;
  }
}
