// Copyright (C) 2008 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.patches;

import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.SignedInListener;
import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.data.AccountInfoCache;
import com.google.gerrit.client.reviewdb.Patch;
import com.google.gerrit.client.reviewdb.PatchLineComment;
import com.google.gerrit.client.reviewdb.PatchSet;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.ComplexDisclosurePanel;
import com.google.gerrit.client.ui.FancyFlexTable;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtjsonrpc.client.VoidResult;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

public abstract class AbstractPatchContentTable extends FancyFlexTable<Object> {
  private static final long AGE = 7 * 24 * 60 * 60 * 1000L;
  protected AccountInfoCache accountCache = AccountInfoCache.empty();
  protected Patch.Key patchKey;
  protected List<PatchSet.Id> versions;
  private final Timestamp aged =
      new Timestamp(System.currentTimeMillis() - AGE);
  private final SignedInListener signedInListener = new SignedInListener() {
    public void onSignIn() {
      if (patchKey != null) {
        PatchUtil.DETAIL_SVC.myDrafts(patchKey,
            new GerritCallback<List<PatchLineComment>>() {
              public void onSuccess(final List<PatchLineComment> result) {
                if (!result.isEmpty()) {
                  bindDrafts(result);
                }
              }
            });
      }
    }

    public void onSignOut() {
      // TODO we should probably confirm with the user before sign out starts
      // that its OK to sign out if any of our editors are unsaved.
      // (bug GERRIT-16)
      //
      for (int row = 0; row < table.getRowCount();) {
        final int nCells = table.getCellCount(row);
        int inc = 1;
        for (int cell = 0; cell < nCells; cell++) {
          if (table.getWidget(row, cell) instanceof CommentEditorPanel) {
            destroyEditor(table, row, cell);
            inc = 0;
          }
        }
        row += inc;
      }
    }
  };

  protected AbstractPatchContentTable() {
    table.setStyleName("gerrit-PatchContentTable");
  }

  @Override
  public void onLoad() {
    super.onLoad();
    Gerrit.addSignedInListener(signedInListener);
  }

  @Override
  public void onUnload() {
    Gerrit.removeSignedInListener(signedInListener);
    super.onUnload();
  }

  @Override
  protected MyFlexTable createFlexTable() {
    return new DoubleClickFlexTable();
  }

  @Override
  protected boolean onKeyPress(final char keyCode, final int modifiers) {
    if (modifiers == 0) {
      switch (keyCode) {
        case KeyboardListener.KEY_UP:
        case KeyboardListener.KEY_DOWN:
          return false;

        case 'c':
        case 'r':
          for (int row = getCurrentRow(); 0 <= row; row--) {
            final Object item = getRowItem(row);
            if (!(item instanceof CommentList) && item != null) {
              onOpenItem(item);
              break;
            }
          }
          return true;
      }
    }
    return super.onKeyPress(keyCode, modifiers);
  }

  @Override
  protected Object getRowItemKey(final Object item) {
    return null;
  }

  /** Invoked when the user clicks on a table cell. */
  protected abstract void onCellDoubleClick(int row, int column);

  protected abstract void bindDrafts(List<PatchLineComment> drafts);

  protected void initVersions(int fileCnt) {
    if (versions == null) {
      versions = new ArrayList<PatchSet.Id>();
      for (int file = 0; file < fileCnt - 1; file++) {
        versions.add(PatchSet.BASE);
      }
      versions.add(patchKey.getParentKey());
    }
  }

  protected List<PatchSet.Id> getVersions() {
    return versions;
  }

  protected PatchSet.Id getVersion(final int fileId) {
    return versions.get(fileId);
  }

  protected void setVersion(final int fileId, final PatchSet.Id v) {
    versions.set(fileId, v);
  }

  protected int fileFor(final PatchLineComment c) {
    int fileId;
    for (fileId = 0; fileId < versions.size(); fileId++) {
      final PatchSet.Id i = versions.get(fileId);
      if (PatchSet.BASE.equals(i) && c.getSide() == fileId
          && patchKey.equals(c.getKey().getParentKey())) {
        break;
      }
      if (c.getSide() == versions.size() - 1
          && i.equals(c.getKey().getParentKey().getParentKey())) {
        break;
      }
    }
    return fileId;
  }

  protected void createCommentEditor(final int suggestRow, final int column,
      final int line, final short file) {
    int row = suggestRow;
    int spans[] = new int[column + 1];
    OUTER: while (row < table.getRowCount()) {
      int col = 0;
      for (int cell = 0; cell < table.getCellCount(row); cell++) {
        while (col < column && 0 < spans[col]) {
          spans[col++]--;
        }
        spans[col] = table.getFlexCellFormatter().getRowSpan(row, cell);
        if (col == column) {
          if (table.getWidget(row, cell) instanceof ComplexDisclosurePanel) {
            row++;
          } else {
            break OUTER;
          }
        }
      }
    }
    if (column < table.getCellCount(row)
        && table.getWidget(row, column) instanceof CommentEditorPanel) {
      // Don't insert two editors on the same position, it doesn't make
      // any sense to the user.
      //
      ((CommentEditorPanel) table.getWidget(row, column)).setFocus(true);
      return;
    }

    if (!Gerrit.isSignedIn()) {
      Gerrit.doSignIn(new AsyncCallback<VoidResult>() {
        public void onSuccess(final VoidResult result) {
          createCommentEditor(suggestRow, column, line, file);
        }

        public void onFailure(Throwable caught) {
        }
      });
      return;
    }

    final Patch.Key parentKey;
    final short side;
    if (PatchSet.BASE.equals(getVersion(file))) {
      parentKey = patchKey;
      side = file;
    } else {
      parentKey = new Patch.Key(getVersion(file), patchKey.get());
      side = (short) 1;
    }
    final PatchLineComment newComment =
        new PatchLineComment(new PatchLineComment.Key(parentKey, null), line,
            Gerrit.getUserAccount().getId());
    newComment.setSide(side);
    newComment.setMessage("");

    final CommentEditorPanel ed = new CommentEditorPanel(newComment);
    boolean needInsert = true;
    for (int cell = 0; cell < table.getCellCount(row); cell++) {
      final Widget w = table.getWidget(row, cell);
      if (w instanceof CommentEditorPanel
          || w instanceof ComplexDisclosurePanel) {
        needInsert = false;
        break;
      }
    }
    if (needInsert) {
      table.insertRow(row);
      table.getCellFormatter().setStyleName(row, 0, S_ICON_CELL);
    }
    table.setWidget(row, column, ed);
    table.getFlexCellFormatter().setStyleName(row, column, "Comment");

    int span = 1;
    for (int r = row + 1; r < table.getRowCount(); r++) {
      boolean hasComment = false;
      for (int c = 0; c < table.getCellCount(r); c++) {
        final Widget w = table.getWidget(r, c);
        if (w instanceof ComplexDisclosurePanel
            || w instanceof CommentEditorPanel) {
          hasComment = true;
          break;
        }
      }
      if (hasComment) {
        table.removeCell(r, column);
        span++;
      } else {
        break;
      }
    }
    if (span > 1) {
      table.getFlexCellFormatter().setRowSpan(row, column, span);
    }

    for (int r = row - 1; r > 0; r--) {
      if (getRowItem(r) instanceof CommentList) {
        continue;
      } else if (getRowItem(r) != null) {
        movePointerTo(r);
        break;
      }
    }

    ed.setFocus(true);
  }

  @Override
  protected void onOpenItem(final Object item) {
    if (item instanceof CommentList) {
      for (final ComplexDisclosurePanel p : ((CommentList) item).panels) {
        p.setOpen(!p.isOpen());
      }
    }
  }

  public void setAccountInfoCache(final AccountInfoCache aic) {
    assert aic != null;
    accountCache = aic;
  }

  public void setPatchKey(final Patch.Key id) {
    patchKey = id;
  }

  static void destroyEditor(final FlexTable table, final int row, final int col) {
    table.clearCell(row, col);
    final int span = table.getFlexCellFormatter().getRowSpan(row, col);
    boolean removeRow = true;
    final int nCells = table.getCellCount(row);
    for (int cell = 0; cell < nCells; cell++) {
      if (table.getWidget(row, cell) != null) {
        removeRow = false;
        break;
      }
    }
    if (removeRow) {
      for (int r = row - 1; 0 <= r; r--) {
        boolean data = false;
        for (int c = 0; c < table.getCellCount(r); c++) {
          data |= table.getWidget(r, c) != null;
          final int s = table.getFlexCellFormatter().getRowSpan(r, c) - 1;
          if (r + s == row) {
            table.getFlexCellFormatter().setRowSpan(r, c, s);
          }
        }
        if (!data) {
          break;
        }
      }
      table.removeRow(row);
    } else if (span != 1) {
      table.getFlexCellFormatter().setRowSpan(row, col, 1);
      for (int r = row + 1; r < row + span; r++) {
        table.insertCell(r, col + 1);
      }
    }
  }

  protected void bindComment(final int row, final int col,
      final PatchLineComment line, final boolean isLast) {
    if (line.getStatus() == PatchLineComment.Status.DRAFT) {
      boolean takeFocus = false;
      if (row + 1 < table.getRowCount() && col < table.getCellCount(row + 1)
          && table.getWidget(row + 1, col) instanceof CommentEditorPanel
          && ((CommentEditorPanel) table.getWidget(row + 1, col)).isNew()) {
        // Assume the second panel is a new one created while logging in;
        // this line is from the myDrafts callback and we discovered we
        // already have a draft at this location. We want to destroy the
        // dummy editor and keep the real one.
        //
        destroyEditor(table, row + 1, col);
        takeFocus = true;
      }
      final CommentEditorPanel plc = new CommentEditorPanel(line);
      table.setWidget(row, col, plc);
      table.getFlexCellFormatter().setStyleName(row, col, "Comment");
      if (takeFocus) {
        plc.setFocus(true);
      }
      return;
    }

    final LineCommentPanel mp = new LineCommentPanel(line);
    String panelHeader;
    final ComplexDisclosurePanel panel;

    if (line.getAuthor() != null) {
      panelHeader = FormatUtil.nameEmail(accountCache.get(line.getAuthor()));
    } else {
      panelHeader = Util.C.messageNoAuthor();
    }

    if (isLast) {
      mp.isRecent = true;
    } else {
      // TODO Instead of opening messages by strict age, do it by "unread"?
      mp.isRecent = line.getWrittenOn().after(aged);
    }

    panel = new ComplexDisclosurePanel(panelHeader, mp.isRecent);
    panel.getHeader().add(
        new InlineLabel(Util.M.messageWrittenOn(FormatUtil.mediumFormat(line
            .getWrittenOn()))));
    panel.setContent(mp);
    table.setWidget(row, col, panel);
    table.getFlexCellFormatter().setStyleName(row, col, "Comment");

    CommentList l = (CommentList) getRowItem(row);
    if (l == null) {
      l = new CommentList();
      setRowItem(row, l);
    }
    l.comments.add(line);
    l.panels.add(panel);
  }

  protected static class CommentList {
    final List<PatchLineComment> comments = new ArrayList<PatchLineComment>();
    final List<ComplexDisclosurePanel> panels =
        new ArrayList<ComplexDisclosurePanel>();
  }

  protected class DoubleClickFlexTable extends MyFlexTable {
    public DoubleClickFlexTable() {
      sinkEvents(Event.ONDBLCLICK | Event.ONCLICK);
    }

    @Override
    public void onBrowserEvent(final Event event) {
      switch (DOM.eventGetType(event)) {
        case Event.ONCLICK: {
          // Find out which cell was actually clicked.
          final Element td = getEventTargetCell(event);
          if (td == null) {
            break;
          }
          final Element tr = DOM.getParent(td);
          final Element body = DOM.getParent(tr);
          final int row = DOM.getChildIndex(body, tr);
          if (getRowItem(row) != null) {
            movePointerTo(row);
            return;
          }
          break;
        }
        case Event.ONDBLCLICK: {
          // Find out which cell was actually clicked.
          Element td = getEventTargetCell(event);
          if (td == null) {
            return;
          }
          Element tr = DOM.getParent(td);
          Element body = DOM.getParent(tr);
          int row = DOM.getChildIndex(body, tr);
          int column = DOM.getChildIndex(tr, td);
          onCellDoubleClick(row, column);
          return;
        }
      }
      super.onBrowserEvent(event);
    }
  }
}
