// 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.change;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.changes.CommentInfo;
import com.google.gerrit.client.changes.ReviewInfo;
import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.diff.FileInfo;
import com.google.gerrit.client.patches.PatchUtil;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.ui.NavigationTable;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.Patch.ChangeType;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.impl.HyperlinkImpl;
import com.google.gwtexpui.globalkey.client.KeyCommand;
import com.google.gwtexpui.progress.client.ProgressBar;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import com.google.gwtorm.client.KeyUtil;

import java.sql.Timestamp;

class FileTable extends FlowPanel {
  static final FileTableResources R = GWT
      .create(FileTableResources.class);

  interface FileTableResources extends ClientBundle {
    @Source("file_table.css")
    FileTableCss css();
  }

  interface FileTableCss extends CssResource {
    String pointer();
    String reviewed();
    String status();
    String pathColumn();
    String draftColumn();
    String newColumn();
    String commentColumn();
    String deltaColumn1();
    String deltaColumn2();
    String commonPrefix();
    String inserted();
    String deleted();
  }

  private static final String REVIEWED;
  private static final String OPEN;
  private static final HyperlinkImpl link = GWT.create(HyperlinkImpl.class);

  static {
    REVIEWED = DOM.createUniqueId().replace('-', '_');
    OPEN = DOM.createUniqueId().replace('-', '_');
    init(REVIEWED, OPEN);
  }

  private static final native void init(String r, String o) /*-{
    $wnd[r] = $entry(function(e,i) {
      @com.google.gerrit.client.change.FileTable::onReviewed(Lcom/google/gwt/dom/client/NativeEvent;I)(e,i)
    });
    $wnd[o] = $entry(function(e,i) {
      return @com.google.gerrit.client.change.FileTable::onOpen(Lcom/google/gwt/dom/client/NativeEvent;I)(e,i);
    });
  }-*/;

  private static void onReviewed(NativeEvent e, int idx) {
    MyTable t = getMyTable(e);
    if (t != null) {
      t.onReviewed(InputElement.as(Element.as(e.getEventTarget())), idx);
    }
  }

  private static boolean onOpen(NativeEvent e, int idx) {
    if (link.handleAsClick(e.<Event> cast())) {
      MyTable t = getMyTable(e);
      if (t != null) {
        t.onOpenRow(1 + idx);
        e.preventDefault();
        return false;
      }
    }
    return true;
  }

  private static MyTable getMyTable(NativeEvent event) {
    com.google.gwt.user.client.Element e = event.getEventTarget().cast();
    for (e = DOM.getParent(e); e != null; e = DOM.getParent(e)) {
      EventListener l = DOM.getEventListener(e);
      if (l instanceof MyTable) {
        return (MyTable) l;
      }
    }
    return null;
  }

  private PatchSet.Id base;
  private PatchSet.Id curr;
  private MyTable table;
  private boolean register;
  private JsArrayString reviewed;
  private String scrollToPath;

  @Override
  protected void onLoad() {
    super.onLoad();
    R.css().ensureInjected();
  }

  void setRevisions(PatchSet.Id base, PatchSet.Id curr) {
    this.base = base;
    this.curr = curr;
  }

  void setValue(NativeMap<FileInfo> fileMap,
      Timestamp myLastReply,
      NativeMap<JsArray<CommentInfo>> comments,
      NativeMap<JsArray<CommentInfo>> drafts) {
    JsArray<FileInfo> list = fileMap.values();
    FileInfo.sortFileInfoByPath(list);

    DisplayCommand cmd = new DisplayCommand(fileMap, list,
        myLastReply, comments, drafts);
    if (cmd.execute()) {
      cmd.showProgressBar();
      Scheduler.get().scheduleIncremental(cmd);
    }
  }

  void markReviewed(JsArrayString reviewed) {
    if (table != null) {
      table.markReviewed(reviewed);
    } else {
      this.reviewed = reviewed;
    }
  }

  void registerKeys() {
    register = true;

    if (table != null) {
      table.setRegisterKeys(true);
    }
  }

  void scrollToPath(String path) {
    if (table != null) {
      table.scrollToPath(path);
    } else {
      scrollToPath = path;
    }
  }

  private void setTable(MyTable table) {
    clear();
    add(table);
    this.table = table;

    if (register) {
      table.setRegisterKeys(true);
    }
    if (reviewed != null) {
      table.markReviewed(reviewed);
      reviewed = null;
    }
    if (scrollToPath != null) {
      table.scrollToPath(scrollToPath);
      scrollToPath = null;
    }
  }

  private String url(FileInfo info) {
    // TODO(sop): Switch to Dispatcher.toPatchSideBySide.
    Change.Id c = curr.getParentKey();
    StringBuilder p = new StringBuilder();
    p.append("/c/").append(c).append('/');
    if (base != null) {
      p.append(base.get()).append("..");
    }
    p.append(curr.get()).append('/').append(KeyUtil.encode(info.path()));
    p.append(info.binary() ? ",unified" : ",cm");
    return p.toString();
  }

  private final class MyTable extends NavigationTable<FileInfo> {
    private final NativeMap<FileInfo> map;
    private final JsArray<FileInfo> list;

    MyTable(NativeMap<FileInfo> map, JsArray<FileInfo> list) {
      this.map = map;
      this.list = list;
      table.setWidth("");

      keysNavigation.add(new PrevKeyCommand(0, 'k', Util.C.patchTablePrev()));
      keysNavigation.add(new NextKeyCommand(0, 'j', Util.C.patchTableNext()));
      keysNavigation.add(new OpenKeyCommand(0, 'o', Util.C.patchTableOpenDiff()));
      keysNavigation.add(new OpenKeyCommand(0, KeyCodes.KEY_ENTER,
          Util.C.patchTableOpenDiff()));

      keysAction.add(new KeyCommand(0, 'r', PatchUtil.C.toggleReviewed()) {
        @Override
        public void onKeyPress(KeyPressEvent event) {
          int row = getCurrentRow();
          if (1 <= row && row <= MyTable.this.list.length()) {
            FileInfo info = MyTable.this.list.get(row - 1);
            InputElement b = getReviewed(info);
            boolean c = !b.isChecked();
            setReviewed(info, c);
            b.setChecked(c);
          }
        }
      });

      setSavePointerId(
          (base != null ? base.toString() + ".." : "")
          + curr.toString());
    }

    void onReviewed(InputElement checkbox, int idx) {
      setReviewed(list.get(idx), checkbox.isChecked());
    }

    private void setReviewed(FileInfo info, boolean r) {
      RestApi api = ChangeApi.revision(curr)
          .view("files")
          .id(info.path())
          .view("reviewed");
      if (r) {
        api.put(CallbackGroup.<ReviewInfo>emptyCallback());
      } else {
        api.delete(CallbackGroup.<ReviewInfo>emptyCallback());
      }
    }

    void markReviewed(JsArrayString reviewed) {
      for (int i = 0; i < reviewed.length(); i++) {
        FileInfo info = map.get(reviewed.get(i));
        if (info != null) {
          getReviewed(info).setChecked(true);
        }
      }
    }

    private InputElement getReviewed(FileInfo info) {
      CellFormatter fmt = table.getCellFormatter();
      Element e = fmt.getElement(1 + info._row(), 1);
      return InputElement.as(e.getFirstChildElement());
    }

    void scrollToPath(String path) {
      FileInfo info = map.get(path);
      if (info != null) {
        movePointerTo(1 + info._row(), true);
      }
    }

    @Override
    protected Object getRowItemKey(FileInfo item) {
      return item.path();
    }

    @Override
    protected int findRow(Object id) {
      FileInfo info = map.get((String) id);
      return info != null ? 1 + info._row() : -1;
    }

    @Override
    protected FileInfo getRowItem(int row) {
      if (1 <= row && row <= list.length()) {
        return list.get(row - 1);
      }
      return null;
    }

    @Override
    protected void onOpenRow(int row) {
      if (1 <= row && row <= list.length()) {
        Gerrit.display(url(list.get(row - 1)));
      }
    }
  }

  private final class DisplayCommand implements RepeatingCommand {
    private final SafeHtmlBuilder sb = new SafeHtmlBuilder();
    private final MyTable table;
    private final JsArray<FileInfo> list;
    private final Timestamp myLastReply;
    private final NativeMap<JsArray<CommentInfo>> comments;
    private final NativeMap<JsArray<CommentInfo>> drafts;
    private final boolean hasUser;
    private boolean attached;
    private int row;
    private double start;
    private ProgressBar meter;
    private String lastPath = "";

    private int inserted;
    private int deleted;

    private DisplayCommand(NativeMap<FileInfo> map,
        JsArray<FileInfo> list,
        Timestamp myLastReply,
        NativeMap<JsArray<CommentInfo>> comments,
        NativeMap<JsArray<CommentInfo>> drafts) {
      this.table = new MyTable(map, list);
      this.list = list;
      this.myLastReply = myLastReply;
      this.comments = comments;
      this.drafts = drafts;
      this.hasUser = Gerrit.isSignedIn();
    }

    public boolean execute() {
      boolean attachedNow = isAttached();
      if (!attached && attachedNow) {
        // Remember that we have been attached at least once. If
        // later we find we aren't attached we should stop running.
        attached = true;
      } else if (attached && !attachedNow) {
        // If the user navigated away, we aren't in the DOM anymore.
        // Don't continue to render.
        return false;
      }

      start = System.currentTimeMillis();
      if (row == 0) {
        header(sb);
        computeInsertedDeleted();
      }
      while (row < list.length()) {
        FileInfo info = list.get(row);
        info._row(row);
        render(sb, info);
        if ((++row % 10) == 0 && longRunning()) {
          updateMeter();
          return true;
        }
      }
      footer(sb);
      table.resetHtml(sb);
      table.finishDisplay();
      setTable(table);
      return false;
    }

    private void computeInsertedDeleted() {
      inserted = 0;
      deleted = 0;
      for (int i = 0; i < list.length(); i++) {
        FileInfo info = list.get(i);
        if (!Patch.COMMIT_MSG.equals(info.path()) && !info.binary()) {
          inserted += info.lines_inserted();
          deleted += info.lines_deleted();
        }
      }
    }

    void showProgressBar() {
      if (meter == null) {
        meter = new ProgressBar(Util.M.loadingPatchSet(curr.get()));
        FileTable.this.clear();
        FileTable.this.add(meter);
      }
      updateMeter();
    }

    void updateMeter() {
      if (meter != null) {
        int n = list.length();
        meter.setValue((100 * row) / n);
      }
    }

    private boolean longRunning() {
      return System.currentTimeMillis() - start > 200;
    }

    private void header(SafeHtmlBuilder sb) {
      sb.openTr();
      sb.openTh().setStyleName(R.css().pointer()).closeTh();
      sb.openTh().setStyleName(R.css().reviewed()).closeTh();
      sb.openTh().setStyleName(R.css().status()).closeTh();
      sb.openTh().append(Util.C.patchTableColumnName()).closeTh();
      sb.openTh()
        .setAttribute("colspan", 3)
        .append(Util.C.patchTableColumnComments())
        .closeTh();
      sb.openTh()
        .setAttribute("colspan", 2)
        .append(Util.C.patchTableColumnSize())
        .closeTh();
      sb.closeTr();
    }

    private void render(SafeHtmlBuilder sb, FileInfo info) {
      sb.openTr();
      sb.openTd().setStyleName(R.css().pointer()).closeTd();
      columnReviewed(sb, info);
      columnStatus(sb, info);
      columnPath(sb, info);
      columnComments(sb, info);
      columnDelta1(sb, info);
      columnDelta2(sb, info);
      sb.closeTr();
    }

    private void columnReviewed(SafeHtmlBuilder sb, FileInfo info) {
      sb.openTd().setStyleName(R.css().reviewed());
      if (hasUser) {
        sb.openElement("input")
          .setAttribute("title", Resources.C.reviewedFileTitle())
          .setAttribute("type", "checkbox")
          .setAttribute("onclick", REVIEWED + "(event," + info._row() + ")")
          .closeSelf();
      }
      sb.closeTd();
    }

    private void columnStatus(SafeHtmlBuilder sb, FileInfo info) {
      sb.openTd().setStyleName(R.css().status());
      if (!Patch.COMMIT_MSG.equals(info.path())
          && info.status() != null
          && !ChangeType.MODIFIED.matches(info.status())) {
        sb.append(info.status());
      }
      sb.closeTd();
    }

    private void columnPath(SafeHtmlBuilder sb, FileInfo info) {
      sb.openTd()
        .setStyleName(R.css().pathColumn())
        .openAnchor()
        .setAttribute("href", "#" + url(info))
        .setAttribute("onclick", OPEN + "(event," + info._row() + ")");

      String path = info.path();
      if (Patch.COMMIT_MSG.equals(path)) {
        sb.append(Util.C.commitMessage());
      } else {
        int commonPrefixLen = commonPrefix(path);
        if (commonPrefixLen > 0) {
          sb.openSpan().setStyleName(R.css().commonPrefix())
            .append(path.substring(0, commonPrefixLen))
            .closeSpan();
        }
        sb.append(path.substring(commonPrefixLen));
        lastPath = path;
      }

      sb.closeAnchor()
        .closeTd();
    }

    private int commonPrefix(String path) {
      for (int n = path.length(); n > 0;) {
        int s = path.lastIndexOf('/', n);
        if (s < 0) {
          return 0;
        }

        String p = path.substring(0, s + 1);
        if (lastPath.startsWith(p)) {
          return s + 1;
        }
        n = s - 1;
      }
      return 0;
    }

    private void columnComments(SafeHtmlBuilder sb, FileInfo info) {
      JsArray<CommentInfo> cList = get(info.path(), comments);
      JsArray<CommentInfo> dList = get(info.path(), drafts);

      sb.openTd().setStyleName(R.css().draftColumn());
      if (dList.length() > 0) {
        sb.append("drafts: ").append(dList.length());
      }
      sb.closeTd();

      int cntAll = cList.length();
      int cntNew = 0;
      if (myLastReply != null) {
        for (int i = cntAll - 1; i >= 0; i--) {
          CommentInfo m = cList.get(i);
          if (m.updated().compareTo(myLastReply) > 0) {
            cntNew++;
          } else {
            break;
          }
        }
      }

      sb.openTd().setStyleName(R.css().newColumn());
      if (cntNew > 0) {
        sb.append("new: ").append(cntNew);
      }
      sb.closeTd();

      sb.openTd().setStyleName(R.css().commentColumn());
      if (cntAll - cntNew > 0) {
        sb.append("comments: ").append(cntAll - cntNew);
      }
      sb.closeTd();
    }

    private JsArray<CommentInfo> get(String p, NativeMap<JsArray<CommentInfo>> m) {
      JsArray<CommentInfo> r =  m.get(p);
      if (r == null) {
        r = JsArray.createArray().cast();
      }
      return r;
    }

    private void columnDelta1(SafeHtmlBuilder sb, FileInfo info) {
      sb.openTd().setStyleName(R.css().deltaColumn1());
      if (!Patch.COMMIT_MSG.equals(info.path()) && !info.binary()) {
        sb.append(info.lines_inserted() + info.lines_deleted());
      }
      sb.closeTd();
    }

    private void columnDelta2(SafeHtmlBuilder sb, FileInfo info) {
      sb.openTd().setStyleName(R.css().deltaColumn2());
      if (!Patch.COMMIT_MSG.equals(info.path()) && !info.binary()
          && (info.lines_inserted() != 0 || info.lines_deleted() != 0)) {
        int w = 80;
        int t = inserted + deleted;
        int i = Math.max(5, (int) (((double) w) * info.lines_inserted() / t));
        int d = Math.max(5, (int) (((double) w) * info.lines_deleted() / t));

        sb.setAttribute(
            "title",
            Util.M.patchTableSize_LongModify(info.lines_inserted(),
                info.lines_deleted()));

        if (0 < info.lines_inserted()) {
          sb.openDiv()
            .setStyleName(R.css().inserted())
            .setAttribute("style", "width:" + i + "px")
            .closeDiv();
        }
        if (0 < info.lines_deleted()) {
          sb.openDiv()
            .setStyleName(R.css().deleted())
            .setAttribute("style", "width:" + d + "px")
            .closeDiv();
        }
      }
      sb.closeTd();
    }

    private void footer(SafeHtmlBuilder sb) {
      sb.openTr();
      sb.openTh().setStyleName(R.css().pointer()).closeTh();
      sb.openTh().setStyleName(R.css().reviewed()).closeTh();
      sb.openTh().setStyleName(R.css().status()).closeTh();
      sb.openTd().closeTd(); // path
      sb.openTd().setAttribute("colspan", 3).closeTd(); // comments

      // delta1
      sb.openTh().setStyleName(R.css().deltaColumn1())
        .append(Util.M.patchTableSize_Modify(inserted, deleted))
        .closeTh();

      // delta2
      sb.openTh().setStyleName(R.css().deltaColumn2());
      int w = 80;
      int t = inserted + deleted;
      int i = Math.max(1, (int) (((double) w) * inserted / t));
      int d = Math.max(1, (int) (((double) w) * deleted / t));
      if (i + d > w && i > d) {
        i = w - d;
      } else if (i + d > w && d > i) {
        d = w - i;
      }
      if (0 < inserted) {
        sb.openDiv()
        .setStyleName(R.css().inserted())
        .setAttribute("style", "width:" + i + "px")
        .closeDiv();
      }
      if (0 < deleted) {
        sb.openDiv()
          .setStyleName(R.css().deleted())
          .setAttribute("style", "width:" + d + "px")
          .closeDiv();
      }
      sb.closeTh();

      sb.closeTr();
    }
  }
}
