// 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.diff.LineMapper.LineOnOtherInfo;
import com.google.gerrit.client.diff.UnifiedChunkManager.LineRegionInfo;
import com.google.gerrit.client.diff.UnifiedChunkManager.RegionType;
import com.google.gerrit.client.ui.CommentLinkProcessor;
import com.google.gerrit.reviewdb.client.PatchSet;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
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 Unified}. */
class UnifiedCommentManager extends CommentManager {

  private final SortedMap<Integer, CommentGroup> mergedMap;

  // In Unified, a CodeMirror line can have up to two CommentGroups - one for
  // the base side and one for the revision, so we need to keep track of the
  // duplicates and replace the entries in mergedMap on draft removal.
  private final Map<Integer, CommentGroup> duplicates;

  UnifiedCommentManager(
      Unified host,
      DiffObject base,
      PatchSet.Id revision,
      String path,
      CommentLinkProcessor clp,
      boolean open) {
    super(host, base, revision, path, clp, open);
    mergedMap = new TreeMap<>();
    duplicates = new HashMap<>();
  }

  @Override
  SortedMap<Integer, CommentGroup> getMapForNav(DisplaySide side) {
    return mergedMap;
  }

  @Override
  void clearLine(DisplaySide side, int line, CommentGroup group) {
    super.clearLine(side, line, group);

    if (mergedMap.get(line) == group) {
      mergedMap.remove(line);
      if (duplicates.containsKey(line)) {
        mergedMap.put(line, duplicates.remove(line));
      }
    }
  }

  @Override
  void newDraftOnGutterClick(CodeMirror cm, String gutterClass, int cmLinePlusOne) {
    if (!Gerrit.isSignedIn()) {
      signInCallback(cm).run();
    } else {
      LineRegionInfo info = ((Unified) host).getLineRegionInfoFromCmLine(cmLinePlusOne - 1);
      DisplaySide side =
          gutterClass.equals(UnifiedTable.style.lineNumbersLeft()) ? DisplaySide.A : DisplaySide.B;
      int line = info.line;
      if (info.getSide() != side) {
        line = host.lineOnOther(info.getSide(), line).getLine();
      }
      insertNewDraft(side, line + 1);
    }
  }

  @Override
  CommentGroup getCommentGroupOnActiveLine(CodeMirror cm) {
    CommentGroup group = null;
    if (cm.extras().hasActiveLine()) {
      int cmLinePlusOne = cm.getLineNumber(cm.extras().activeLine()) + 1;
      LineRegionInfo info = ((Unified) host).getLineRegionInfoFromCmLine(cmLinePlusOne - 1);
      CommentGroup forSide = map(info.getSide()).get(cmLinePlusOne);
      group = forSide == null ? map(info.getSide().otherSide()).get(cmLinePlusOne) : forSide;
    }
    return group;
  }

  @Override
  Collection<Integer> getLinesWithCommentGroups() {
    return mergedMap.tailMap(1).keySet();
  }

  @Override
  String getTokenSuffixForActiveLine(CodeMirror cm) {
    int cmLinePlusOne = cm.getLineNumber(cm.extras().activeLine()) + 1;
    LineRegionInfo info = ((Unified) host).getLineRegionInfoFromCmLine(cmLinePlusOne - 1);
    return (info.getSide() == DisplaySide.A ? "a" : "") + cmLinePlusOne;
  }

  @Override
  void newDraft(CodeMirror cm) {
    if (cm.somethingSelected()) {
      FromTo fromTo = adjustSelection(cm);
      Pos from = fromTo.from();
      Pos to = fromTo.to();
      Unified unified = (Unified) host;
      UnifiedChunkManager manager = unified.getChunkManager();
      LineRegionInfo fromInfo = unified.getLineRegionInfoFromCmLine(from.line());
      LineRegionInfo toInfo = unified.getLineRegionInfoFromCmLine(to.line());
      DisplaySide side = toInfo.getSide();

      // Handle special cases in selections that span multiple regions. Force
      // start line to be on the same side as the end line.
      if ((fromInfo.type == RegionType.INSERT || fromInfo.type == RegionType.COMMON)
          && toInfo.type == RegionType.DELETE) {
        LineOnOtherInfo infoOnSideA = manager.lineMapper.lineOnOther(DisplaySide.B, fromInfo.line);
        int startLineOnSideA = infoOnSideA.getLine();
        if (infoOnSideA.isAligned()) {
          from.line(startLineOnSideA);
        } else {
          from.line(startLineOnSideA + 1);
        }
        from.ch(0);
        to.line(toInfo.line);
      } else if (fromInfo.type == RegionType.DELETE && toInfo.type == RegionType.INSERT) {
        LineOnOtherInfo infoOnSideB = manager.lineMapper.lineOnOther(DisplaySide.A, fromInfo.line);
        int startLineOnSideB = infoOnSideB.getLine();
        if (infoOnSideB.isAligned()) {
          from.line(startLineOnSideB);
        } else {
          from.line(startLineOnSideB + 1);
        }
        from.ch(0);
        to.line(toInfo.line);
      } else if (fromInfo.type == RegionType.DELETE && toInfo.type == RegionType.COMMON) {
        int toLineOnSideA = manager.lineMapper.lineOnOther(DisplaySide.B, toInfo.line).getLine();
        from.line(fromInfo.line);
        // Force the end line to be on the same side as the start line.
        to.line(toLineOnSideA);
        side = DisplaySide.A;
      } else { // Common case
        from.line(fromInfo.line);
        to.line(toInfo.line);
      }

      addDraftBox(
              side,
              CommentInfo.create(
                  getPath(),
                  getStoredSideFromDisplaySide(side),
                  to.line() + 1,
                  CommentRange.create(fromTo),
                  false))
          .setEdit(true);
      cm.setCursor(Pos.create(host.getCmLine(to.line(), side), to.ch()));
      cm.setSelection(cm.getCursor());
    } else {
      int cmLine = cm.getLineNumber(cm.extras().activeLine());
      LineRegionInfo info = ((Unified) host).getLineRegionInfoFromCmLine(cmLine);
      insertNewDraft(info.getSide(), cmLine + 1);
    }
  }

  @Override
  CommentGroup group(DisplaySide side, int cmLinePlusOne) {
    Map<Integer, CommentGroup> map = map(side);
    CommentGroup existing = map.get(cmLinePlusOne);
    if (existing != null) {
      return existing;
    }

    UnifiedCommentGroup g =
        new UnifiedCommentGroup(this, host.getCmFromSide(side), side, cmLinePlusOne);
    map.put(cmLinePlusOne, g);
    if (mergedMap.containsKey(cmLinePlusOne)) {
      duplicates.put(cmLinePlusOne, mergedMap.remove(cmLinePlusOne));
    }
    mergedMap.put(cmLinePlusOne, g);

    if (isAttached()) {
      g.init(host.getDiffTable());
      g.handleRedraw();
    }

    return g;
  }
}
