// 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.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.
 */
abstract class CommentGroup extends Composite {

  final DisplaySide side;
  final int line;

  private final CommentManager manager;
  private final CodeMirror cm;
  private final FlowPanel comments;
  private LineWidget lineWidget;
  private Timer resizeTimer;

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

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

  CommentManager getCommentManager() {
    return manager;
  }

  CodeMirror getCm() {
    return cm;
  }

  int getLine() {
    return line;
  }

  DisplaySide getSide() {
    return side;
  }

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

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

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

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

  void updateSelection() {
    if (cm.somethingSelected()) {
      FromTo r = cm.getSelectedRange();
      if (r.to().line() >= line) {
        cm.setSelection(r.from(), r.to());
      }
    }
  }

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

  LineWidget getLineWidget() {
    return lineWidget;
  }

  void setLineWidget(LineWidget widget) {
    lineWidget = widget;
  }

  Timer getResizeTimer() {
    return resizeTimer;
  }

  void setResizeTimer(Timer timer) {
    resizeTimer = timer;
  }

  FlowPanel getComments() {
    return comments;
  }

  CommentManager getManager() {
    return manager;
  }

  abstract void init(DiffTable parent);

  abstract void handleRedraw();

  abstract void resize();
}
