// 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.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.SimplePanel;

import net.codemirror.lib.CodeMirror;
import net.codemirror.lib.Configuration;
import net.codemirror.lib.LineWidget;
import net.codemirror.lib.TextMarker.FromTo;

/**
 * LineWidget attached to a CodeMirror container.
 *
 * When a comment is placed on a line a CommentWidget is created on both sides.
 * The group tracks all comment boxes on that same line, and also includes an
 * empty padding element to keep subsequent lines vertically aligned.
 */
class CommentGroup extends Composite {
  static void pair(CommentGroup a, CommentGroup b) {
    a.peer = b;
    b.peer = a;
  }

  private final CommentManager manager;
  private final CodeMirror cm;
  private final int line;
  private final FlowPanel comments;
  private final Element padding;
  private LineWidget lineWidget;
  private Timer resizeTimer;
  private CommentGroup peer;

  CommentGroup(CommentManager manager, CodeMirror cm, int line) {
    this.manager = manager;
    this.cm = cm;
    this.line = line;

    comments = new FlowPanel();
    comments.setStyleName(Resources.I.style().commentWidgets());
    comments.setVisible(false);
    initWidget(new SimplePanel(comments));

    padding = DOM.createDiv();
    padding.setClassName(DiffTable.style.padding());
    getElement().appendChild(padding);
  }

  CommentManager getCommentManager() {
    return manager;
  }

  CodeMirror getCm() {
    return cm;
  }

  CommentGroup getPeer() {
    return peer;
  }

  int getLine() {
    return line;
  }

  void add(PublishedBox box) {
    comments.add(box);
    comments.setVisible(true);
  }

  void add(DraftBox box) {
    PublishedBox p = box.getReplyToBox();
    if (p != null) {
      for (int i = 0; i < getBoxCount(); i++) {
        if (p == getCommentBox(i)) {
          comments.insert(box, i + 1);
          comments.setVisible(true);
          resize();
          return;
        }
      }
    }
    comments.add(box);
    comments.setVisible(true);
    resize();
  }

  CommentBox getCommentBox(int i) {
    return (CommentBox) comments.getWidget(i);
  }

  int getBoxCount() {
    return comments.getWidgetCount();
  }

  void openCloseLast() {
    if (0 < getBoxCount()) {
      CommentBox box = getCommentBox(getBoxCount() - 1);
      box.setOpen(!box.isOpen());
    }
  }

  void openCloseAll() {
    boolean open = false;
    for (int i = 0; i < getBoxCount(); i++) {
      if (!getCommentBox(i).isOpen()) {
        open = true;
        break;
      }
    }
    setOpenAll(open);
  }

  void setOpenAll(boolean open) {
    for (int i = 0; i < getBoxCount(); i++) {
      getCommentBox(i).setOpen(open);
    }
  }

  void remove(DraftBox box) {
    comments.remove(box);
    comments.setVisible(0 < getBoxCount());

    if (0 < getBoxCount() || 0 < peer.getBoxCount()) {
      resize();
    } else {
      detach();
      peer.detach();
    }
  }

  private void detach() {
    if (lineWidget != null) {
      lineWidget.clear();
      lineWidget = null;
      updateSelection();
    }
    manager.clearLine(cm.side(), line, this);
    removeFromParent();
  }

  void attachPair(DiffTable parent) {
    if (lineWidget == null && peer.lineWidget == null) {
      this.attach(parent);
      peer.attach(parent);
    }
  }

  private void attach(DiffTable parent) {
    parent.add(this);
    lineWidget = cm.addLineWidget(Math.max(0, line - 1), getElement(),
        Configuration.create()
          .set("coverGutter", true)
          .set("noHScroll", true)
          .set("above", line <= 0)
          .set("insertAt", 0));
  }

  void handleRedraw() {
    lineWidget.onRedraw(new Runnable() {
      @Override
      public void run() {
        if (canComputeHeight() && peer.canComputeHeight()) {
          if (resizeTimer != null) {
            resizeTimer.cancel();
            resizeTimer = null;
          }
          adjustPadding(CommentGroup.this, peer);
        } else if (resizeTimer == null) {
          resizeTimer = new Timer() {
            @Override
            public void run() {
              if (canComputeHeight() && peer.canComputeHeight()) {
                cancel();
                resizeTimer = null;
                adjustPadding(CommentGroup.this, peer);
              }
            }
          };
          resizeTimer.scheduleRepeating(5);
        }
      }
    });
  }

  @Override
  protected void onUnload() {
    super.onUnload();
    if (resizeTimer != null) {
      resizeTimer.cancel();
    }
  }

  void resize() {
    if (lineWidget != null) {
      adjustPadding(this, peer);
    }
  }

  private void updateSelection() {
    if (cm.somethingSelected()) {
      FromTo r = cm.getSelectedRange();
      if (r.getTo().getLine() >= line) {
        cm.setSelection(r.getFrom(), r.getTo());
      }
    }
  }

  private boolean canComputeHeight() {
    return !comments.isVisible() || comments.getOffsetHeight() > 0;
  }

  private int computeHeight() {
    if (comments.isVisible()) {
      // Include margin-bottom: 5px from CSS class.
      return comments.getOffsetHeight() + 5;
    }
    return 0;
  }

  private static void adjustPadding(CommentGroup a, CommentGroup b) {
    int apx = a.computeHeight();
    int bpx = b.computeHeight();
    int h = Math.max(apx, bpx);
    a.padding.getStyle().setHeight(Math.max(0, h - apx), Unit.PX);
    b.padding.getStyle().setHeight(Math.max(0, h - bpx), Unit.PX);
    a.lineWidget.changed();
    b.lineWidget.changed();
    a.updateSelection();
    b.updateSelection();
  }
}
