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

import com.google.gerrit.client.Dispatcher;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.patches.PatchScreen;
import com.google.gerrit.client.ui.InlineHyperlink;
import com.google.gerrit.client.ui.ListenableAccountDiffPreference;
import com.google.gerrit.client.ui.NavigationTable;
import com.google.gerrit.client.ui.PatchLink;
import com.google.gerrit.common.data.PatchSetDetail;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.Patch.ChangeType;
import com.google.gerrit.reviewdb.client.Patch.Key;
import com.google.gerrit.reviewdb.client.Patch.PatchType;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLTable.Cell;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.globalkey.client.KeyCommand;
import com.google.gwtexpui.progress.client.ProgressBar;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PatchTable extends Composite {
  public interface PatchValidator {
    /**
     * Returns true if patch is valid
     *
     * @param patch
     * @return
     */
    boolean isValid(Patch patch);
  }

  public final PatchValidator PREFERENCE_VALIDATOR =
      new PatchValidator() {
        @Override
        public boolean isValid(Patch patch) {
          return !((listenablePrefs.get().isSkipDeleted()
              && patch.getChangeType().equals(ChangeType.DELETED))
              || (listenablePrefs.get().isSkipUncommented()
              && patch.getCommentCount() == 0));
        }

      };

  private final FlowPanel myBody;
  private PatchSetDetail detail;
  private Command onLoadCommand;
  private MyTable myTable;
  private String savePointerId;
  private PatchSet.Id base;
  private List<Patch> patchList;
  private Map<Patch.Key, Integer> patchMap;
  private ListenableAccountDiffPreference listenablePrefs;

  private List<ClickHandler> clickHandlers;
  private boolean active;
  private boolean registerKeys;

  public PatchTable(ListenableAccountDiffPreference prefs) {
    listenablePrefs = prefs;
    myBody = new FlowPanel();
    initWidget(myBody);
  }

  public PatchTable() {
    this(new ListenableAccountDiffPreference());
  }

  public int indexOf(Patch.Key patch) {
    Integer i = patchMap().get(patch);
    return i != null ? i : -1;
  }

  private Map<Key, Integer> patchMap() {
    if (patchMap == null) {
      patchMap = new HashMap<Patch.Key, Integer>();
      for (int i = 0; i < patchList.size(); i++) {
        patchMap.put(patchList.get(i).getKey(), i);
      }
    }
    return patchMap;
  }

  public void display(PatchSet.Id base, PatchSetDetail detail) {
    this.base = base;
    this.detail = detail;
    this.patchList = detail.getPatches();
    this.patchMap = null;
    myTable = null;

    final DisplayCommand cmd = new DisplayCommand(patchList, base);
    if (cmd.execute()) {
      cmd.initMeter();
      Scheduler.get().scheduleIncremental(cmd);
    } else {
      cmd.showTable();
    }
  }

  public PatchSet.Id getBase() {
    return base;
  }

  public void setSavePointerId(final String id) {
    savePointerId = id;
  }

  public boolean isLoaded() {
    return myTable != null;
  }

  public void onTableLoaded(final Command cmd) {
    if (myTable != null) {
      cmd.execute();
    } else {
      onLoadCommand = cmd;
    }
  }

  public void addClickHandler(final ClickHandler clickHandler) {
    if (myTable != null) {
      myTable.addClickHandler(clickHandler);
    } else {
      if (clickHandlers == null) {
        clickHandlers = new ArrayList<ClickHandler>(2);
      }
      clickHandlers.add(clickHandler);
    }
  }

  public void setRegisterKeys(final boolean on) {
    registerKeys = on;
    if (myTable != null) {
      myTable.setRegisterKeys(on);
    }
  }

  public void movePointerTo(final Patch.Key k) {
    if (myTable != null) {
      myTable.movePointerTo(k);
    }
  }

  public void setActive(boolean active) {
    this.active = active;
    if (myTable != null) {
      myTable.setActive(active);
    }
  }

  public void notifyDraftDelta(final Patch.Key k, final int delta) {
    if (myTable != null) {
      myTable.notifyDraftDelta(k, delta);
    }
  }

  private void setMyTable(MyTable table) {
    myBody.clear();
    myBody.add(table);
    myTable = table;

    if (clickHandlers != null) {
      for (ClickHandler ch : clickHandlers) {
        myTable.addClickHandler(ch);
      }
      clickHandlers = null;
    }

    if (active) {
      myTable.setActive(true);
      active = false;
    }

    if (registerKeys) {
      myTable.setRegisterKeys(registerKeys);
      registerKeys = false;
    }

    myTable.finishDisplay();
  }

  /**
   * @return a link to the previous file in this patch set, or null.
   */
  public InlineHyperlink getPreviousPatchLink(int index,
      PatchScreen.Type patchType) {
    int previousPatchIndex = getPreviousPatch(index, PREFERENCE_VALIDATOR);
    if (previousPatchIndex < 0) {
      return null;
    }
    InlineHyperlink link =
        createLink(previousPatchIndex, patchType,
            SafeHtml.asis(Util.C.prevPatchLinkIcon()), null);

    return link;
  }

  /**
   * @return a link to the next file in this patch set, or null.
   */
  public InlineHyperlink getNextPatchLink(int index, PatchScreen.Type patchType) {
    int nextPatchIndex = getNextPatch(index, false, PREFERENCE_VALIDATOR);
    if (nextPatchIndex < 0) {
      return null;
    }
    InlineHyperlink link =
        createLink(nextPatchIndex, patchType, null,
            SafeHtml.asis(Util.C.nextPatchLinkIcon()));

    return link;
  }

  /**
   * @return a link to the the given patch.
   * @param index The patch to link to
   * @param patchType The type of patch display
   * @param before A string to display at the beginning of the href text
   * @param after A string to display at the end of the href text
   */
  public PatchLink createLink(int index, PatchScreen.Type patchType,
      SafeHtml before, SafeHtml after) {
    Patch patch = patchList.get(index);

    Key thisKey = patch.getKey();
    PatchLink link;
    if (patchType == PatchScreen.Type.SIDE_BY_SIDE) {
      link = new PatchLink.SideBySide("", base, thisKey, index, detail, this);
    } else {
      link = new PatchLink.Unified("", base, thisKey, index, detail, this);
    }
    SafeHtmlBuilder text = new SafeHtmlBuilder();
    text.append(before);
    text.append(getFileNameOnly(patch));
    text.append(after);
    SafeHtml.set(link, text);
    return link;
  }

  private static String getFileNameOnly(Patch patch) {
    // Note: use '/' here and not File.pathSeparator since git paths
    // are always separated by /
    //
    String fileName = getDisplayFileName(patch);
    int s = fileName.lastIndexOf('/');
    if (s >= 0) {
      fileName = fileName.substring(s + 1);
    }
    return fileName;
  }

  public static String getDisplayFileName(Patch patch) {
    return getDisplayFileName(patch.getKey());
  }

  public static String getDisplayFileName(Patch.Key patchKey) {
    if (Patch.COMMIT_MSG.equals(patchKey.get())) {
      return Util.C.commitMessage();
    }
    return patchKey.get();
  }

  /**
   * Update the reviewed status for the given patch.
   */
  public void updateReviewedStatus(Patch.Key patchKey, boolean reviewed) {
    if (myTable != null) {
      myTable.updateReviewedStatus(patchKey, reviewed);
    }
  }

  public ListenableAccountDiffPreference getPreferences() {
    return listenablePrefs;
  }

  private class MyTable extends NavigationTable<Patch> {
    private static final int C_PATH = 2;
    private static final int C_DRAFT = 3;
    private static final int C_SIZE = 4;
    private static final int C_SIDEBYSIDE = 5;
    private int activeRow = -1;

    MyTable() {
      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()));
      keysNavigation.add(new OpenUnifiedDiffKeyCommand(0, 'O', Util.C
          .patchTableOpenUnifiedDiff()));

      table.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(final ClickEvent event) {
          final Cell cell = table.getCellForEvent(event);
          if (cell != null && cell.getRowIndex() > 0) {
            movePointerTo(cell.getRowIndex());
          }
        }
      });
      setSavePointerId(PatchTable.this.savePointerId);
    }

    public void addClickHandler(final ClickHandler clickHandler) {
      table.addClickHandler(clickHandler);
    }

    void updateReviewedStatus(final Patch.Key patchKey, boolean reviewed) {
      int idx = patchMap().get(patchKey);
      if (0 <= idx) {
        Patch patch = patchList.get(idx);
        if (patch.isReviewedByCurrentUser() != reviewed) {
          int row = idx + 1;
          int col = C_SIDEBYSIDE + 2;
          if (patch.getPatchType() == Patch.PatchType.BINARY) {
            col = C_SIDEBYSIDE + 3;
          }
          if (reviewed) {
            table.setWidget(row, col, new Image(Gerrit.RESOURCES.greenCheck()));
          } else {
            table.clearCell(row, col);
          }
          patch.setReviewedByCurrentUser(reviewed);
        }
      }
    }

    void notifyDraftDelta(final Patch.Key key, final int delta) {
      int idx = patchMap().get(key);
      if (0 <= idx) {
        Patch p = patchList.get(idx);
        p.setDraftCount(p.getDraftCount() + delta);
        SafeHtmlBuilder m = new SafeHtmlBuilder();
        appendCommentCount(m, p);
        SafeHtml.set(table, idx + 1, C_DRAFT, m);
      }
    }

    @Override
    public void resetHtml(final SafeHtml html) {
      super.resetHtml(html);
    }

    @Override
    public void movePointerTo(Object oldId) {
      super.movePointerTo(oldId);
    }

    /** Activates / Deactivates the key navigation and the highlighting of the current row for this table */
    public void setActive(boolean active) {
      if (active) {
        if(activeRow > 0 && getCurrentRow() != activeRow) {
          super.movePointerTo(activeRow);
          activeRow = -1;
        }
      } else {
        if(getCurrentRow() > 0) {
          activeRow = getCurrentRow();
          super.movePointerTo(-1);
        }
      }
      setRegisterKeys(active);
    }

    void initializeRow(int row) {
      Patch patch = PatchTable.this.patchList.get(row - 1);
      setRowItem(row, patch);

      Widget nameCol;
      nameCol = new PatchLink.SideBySide(getDisplayFileName(patch), base,
          patch.getKey(), row - 1, detail, PatchTable.this);

      if (patch.getSourceFileName() != null) {
        final String text;
        if (patch.getChangeType() == Patch.ChangeType.RENAMED) {
          text = Util.M.renamedFrom(patch.getSourceFileName());
        } else if (patch.getChangeType() == Patch.ChangeType.COPIED) {
          text = Util.M.copiedFrom(patch.getSourceFileName());
        } else {
          text = Util.M.otherFrom(patch.getSourceFileName());
        }
        final Label line = new Label(text);
        line.setStyleName(Gerrit.RESOURCES.css().sourceFilePath());
        final FlowPanel cell = new FlowPanel();
        cell.add(nameCol);
        cell.add(line);
        nameCol = cell;
      }
      table.setWidget(row, C_PATH, nameCol);

      int C_UNIFIED = C_SIDEBYSIDE + 1;

      PatchLink sideBySide =
          new PatchLink.SideBySide(Util.C.patchTableDiffSideBySide(), base,
              patch.getKey(), row - 1, detail, PatchTable.this);
      sideBySide.setStyleName("gwt-Anchor");

      PatchLink unified =
          new PatchLink.Unified(Util.C.patchTableDiffUnified(), base,
              patch.getKey(), row - 1, detail, PatchTable.this);
      unified.setStyleName("gwt-Anchor");

      table.setWidget(row, C_SIDEBYSIDE, sideBySide);
      table.setWidget(row, C_UNIFIED, unified);
    }

    void initializeLastRow(int row) {
      Anchor sideBySide = new Anchor(Util.C.diffAllSideBySide());
      sideBySide.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(ClickEvent event) {
          for (Patch p : detail.getPatches()) {
            openWindow(Dispatcher.toPatchSideBySide(base, p.getKey()));
          }
        }
      });
      table.setWidget(row, C_SIDEBYSIDE - 2, sideBySide);

      int C_UNIFIED = C_SIDEBYSIDE - 2 + 1;
      Anchor unified = new Anchor(Util.C.diffAllUnified());
      unified.addClickHandler(new ClickHandler() {
        public void onClick(ClickEvent event) {
          for (Patch p : detail.getPatches()) {
            openWindow(Dispatcher.toPatchUnified(base, p.getKey()));
          }
        };
      });
      table.setWidget(row, C_UNIFIED, unified);
    }

    private void openWindow(String token) {
      String url = Window.Location.getPath() + "#" + token;
      Window.open(url, "_blank", null);
    }

    void appendHeader(final SafeHtmlBuilder m) {
      m.openTr();

      // Cursor
      m.openTd();
      m.addStyleName(Gerrit.RESOURCES.css().iconHeader());
      m.addStyleName(Gerrit.RESOURCES.css().leftMostCell());
      m.nbsp();
      m.closeTd();

      // Mode
      m.openTd();
      m.setStyleName(Gerrit.RESOURCES.css().iconHeader());
      m.nbsp();
      m.closeTd();

      // "File path"
      m.openTd();
      m.setStyleName(Gerrit.RESOURCES.css().dataHeader());
      m.append(Util.C.patchTableColumnName());
      m.closeTd();

      // "Comments"
      m.openTd();
      m.setStyleName(Gerrit.RESOURCES.css().dataHeader());
      m.append(Util.C.patchTableColumnComments());
      m.closeTd();

      // "Size"
      m.openTd();
      m.setStyleName(Gerrit.RESOURCES.css().dataHeader());
      m.append(Util.C.patchTableColumnSize());
      m.closeTd();

      // "Diff"
      m.openTd();
      m.setStyleName(Gerrit.RESOURCES.css().dataHeader());
      m.setAttribute("colspan", 3);
      m.append(Util.C.patchTableColumnDiff());
      m.closeTd();

      // "Reviewed"
      if (Gerrit.isSignedIn()) {
        m.openTd();
        m.setStyleName(Gerrit.RESOURCES.css().iconHeader());
        m.addStyleName(Gerrit.RESOURCES.css().dataHeader());
        m.append(Util.C.reviewed());
        m.closeTd();
      }

      m.closeTr();
    }

    void appendRow(final SafeHtmlBuilder m, final Patch p,
        final boolean isReverseDiff) {
      m.openTr();

      m.openTd();
      m.addStyleName(Gerrit.RESOURCES.css().iconCell());
      m.addStyleName(Gerrit.RESOURCES.css().leftMostCell());
      m.nbsp();
      m.closeTd();

      m.openTd();
      m.setStyleName(Gerrit.RESOURCES.css().changeTypeCell());
      if (isReverseDiff) {
        m.addStyleName(Gerrit.RESOURCES.css().patchCellReverseDiff());
      }

      if (Patch.COMMIT_MSG.equals(p.getFileName())) {
        m.nbsp();
      } else {
        m.append(p.getChangeType().getCode());
      }
      m.closeTd();

      m.openTd();
      m.addStyleName(Gerrit.RESOURCES.css().dataCell());
      m.addStyleName(Gerrit.RESOURCES.css().filePathCell());
      m.closeTd();

      m.openTd();
      m.addStyleName(Gerrit.RESOURCES.css().dataCell());
      m.addStyleName(Gerrit.RESOURCES.css().commentCell());
      appendCommentCount(m, p);
      m.closeTd();

      m.openTd();
      m.addStyleName(Gerrit.RESOURCES.css().dataCell());

      m.addStyleName(Gerrit.RESOURCES.css().patchSizeCell());
      if (isReverseDiff) {
        m.addStyleName(Gerrit.RESOURCES.css().patchCellReverseDiff());
      }

      appendSize(m, p);
      m.closeTd();

      // Diff
      openlink(m, 2);
      m.closeTd();
      openlink(m, 1);
      m.closeTd();

      // Green check mark if the user is logged in and they reviewed that file
      if (Gerrit.isSignedIn()) {
        m.openTd();
        m.setStyleName(Gerrit.RESOURCES.css().dataCell());
        if (p.isReviewedByCurrentUser()) {
          m.openDiv();
          m.setStyleName(Gerrit.RESOURCES.css().greenCheckClass());
          m.closeSelf();
        }
        m.closeTd();
      }

      m.closeTr();
    }

    void appendLastRow(final SafeHtmlBuilder m, int ins, int dels,
        final boolean isReverseDiff) {
      m.openTr();

      m.openTd();
      m.addStyleName(Gerrit.RESOURCES.css().iconCell());
      m.addStyleName(Gerrit.RESOURCES.css().noborder());
      m.nbsp();
      m.closeTd();

      m.openTd();
      m.setAttribute("colspan", C_SIZE - 1);
      m.closeTd();

      m.openTd();
      m.addStyleName(Gerrit.RESOURCES.css().dataCell());
      m.addStyleName(Gerrit.RESOURCES.css().patchSizeCell());
      m.addStyleName(Gerrit.RESOURCES.css().leftMostCell());

      if (isReverseDiff) {
        m.addStyleName(Gerrit.RESOURCES.css().patchCellReverseDiff());
      }

      m.append(Util.M.patchTableSize_Modify(ins, dels));
      m.closeTd();

      openlink(m, 2);
      m.closeTd();

      openlink(m, 1);
      m.closeTd();

      m.closeTr();
    }

    void appendCommentCount(final SafeHtmlBuilder m, final Patch p) {
      if (p.getCommentCount() > 0) {
        m.append(Util.M.patchTableComments(p.getCommentCount()));
      }
      if (p.getDraftCount() > 0) {
        if (p.getCommentCount() > 0) {
          m.append(", ");
        }
        m.openSpan();
        m.setStyleName(Gerrit.RESOURCES.css().drafts());
        m.append(Util.M.patchTableDrafts(p.getDraftCount()));
        m.closeSpan();
      }
    }

    void appendSize(final SafeHtmlBuilder m, final Patch p) {
      if (Patch.COMMIT_MSG.equals(p.getFileName())) {
        m.nbsp();
        return;
      }

      if (p.getPatchType() == PatchType.UNIFIED) {
        int ins = p.getInsertions();
        int dels = p.getDeletions();

        switch (p.getChangeType()) {
          case ADDED:
            m.append(Util.M.patchTableSize_Lines(ins));
            break;

          case DELETED:
            m.nbsp();
            break;

          case MODIFIED:
          case COPIED:
          case RENAMED:
            m.append(Util.M.patchTableSize_Modify(ins, dels));
            break;

          case REWRITE:
            break;
        }
      } else {
        m.nbsp();
      }
    }

    private void openlink(final SafeHtmlBuilder m, final int colspan) {
      m.openTd();
      m.addStyleName(Gerrit.RESOURCES.css().dataCell());
      m.addStyleName(Gerrit.RESOURCES.css().diffLinkCell());
      m.setAttribute("colspan", colspan);
    }

    @Override
    protected Object getRowItemKey(final Patch item) {
      return item.getKey();
    }

    @Override
    protected void onOpenRow(final int row) {
      Widget link = table.getWidget(row, C_PATH);
      if (link instanceof FlowPanel) {
        link = ((FlowPanel) link).getWidget(0);
      }
      if (link instanceof InlineHyperlink) {
        ((InlineHyperlink) link).go();
      }
    }

    private final class OpenUnifiedDiffKeyCommand extends KeyCommand {

      public OpenUnifiedDiffKeyCommand(int mask, char key, String help) {
        super(mask, key, help);
      }

      @Override
      public void onKeyPress(KeyPressEvent event) {
        Widget link = table.getWidget(getCurrentRow(), C_PATH);
        if (link instanceof FlowPanel) {
          link = ((FlowPanel) link).getWidget(0);
        }
        if (link instanceof PatchLink.Unified) {
          ((InlineHyperlink) link).go();
        } else {
          link = table.getWidget(getCurrentRow(), C_SIDEBYSIDE + 1);
          if (link instanceof PatchLink.Unified) {
            ((InlineHyperlink) link).go();
          }
        }
      }
    }
  }

  private final class DisplayCommand implements RepeatingCommand {
    private final MyTable table;
    private final List<Patch> list;
    private boolean attached;
    private SafeHtmlBuilder nc = new SafeHtmlBuilder();
    private int stage = 0;
    private int row;
    private double start;
    private ProgressBar meter;

    private int insertions;
    private int deletions;

    private final PatchSet.Id psIdToCompareWith;

    private DisplayCommand(final List<Patch> list, final PatchSet.Id psIdToCompareWith) {
      this.table = new MyTable();
      this.list = list;
      this.psIdToCompareWith = psIdToCompareWith;
    }

    /**
     * Add the files contained in the list of patches to the table, one per row.
     */
    @SuppressWarnings("fallthrough")
    public boolean execute() {
      final 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;
      }

      boolean isReverseDiff = false;

      if (psIdToCompareWith != null
          && list.get(0).getKey().getParentKey().get() < psIdToCompareWith.get()) {
        isReverseDiff = true;
      }

      start = System.currentTimeMillis();
      switch (stage) {
        case 0:
          if (row == 0) {
            table.appendHeader(nc);
            table.appendRow(nc, list.get(row++), isReverseDiff);
          }
          while (row < list.size()) {
            Patch p = list.get(row);
            insertions += p.getInsertions();
            deletions += p.getDeletions();
            table.appendRow(nc, p, isReverseDiff);
            if ((++row % 10) == 0 && longRunning()) {
              updateMeter();
              return true;
            }
          }
          table.appendLastRow(nc, insertions, deletions, isReverseDiff);
          table.resetHtml(nc);
          table.initializeLastRow(row + 1);
          nc = null;
          stage = 1;
          row = 0;

        case 1:
          while (row < list.size()) {
            table.initializeRow(row + 1);
            if ((++row % 50) == 0 && longRunning()) {
              updateMeter();
              return true;
            }
          }
          updateMeter();
          showTable();
      }
      return false;
    }

    void showTable() {
      setMyTable(table);

      if (PatchTable.this.onLoadCommand != null) {
        PatchTable.this.onLoadCommand.execute();
        PatchTable.this.onLoadCommand = null;
      }
    }

    void initMeter() {
      if (meter == null) {
        meter = new ProgressBar(Util.M.loadingPatchSet(detail.getPatchSet().getId().get()));
        PatchTable.this.myBody.clear();
        PatchTable.this.myBody.add(meter);
      }
      updateMeter();
    }

    void updateMeter() {
      if (meter != null) {
        final int n = list.size();
        meter.setValue(((100 * (stage * n + row)) / (2 * n)));
      }
    }

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


  /**
   * Gets the next patch
   *
   * @param currentIndex
   * @param validators
   * @param loopAround loops back around to the front and traverses if this is
   *        true
   * @return
   */
  public int getNextPatch(int currentIndex, boolean loopAround,
      PatchValidator... validators) {
    return getNextPatchHelper(currentIndex, loopAround, detail.getPatches()
        .size(), validators);
  }

  /**
   * Helper function for getNextPatch
   *
   * @param currentIndex
   * @param validators
   * @param loopAround
   * @param maxIndex will only traverse up to this index
   * @return
   */
  private int getNextPatchHelper(int currentIndex, boolean loopAround,
      int maxIndex, PatchValidator... validators) {
    for (int i = currentIndex + 1; i < maxIndex; i++) {
      Patch patch = detail.getPatches().get(i);
      if (patch != null && patchIsValid(patch, validators)) {
        return i;
      }
    }

    if (loopAround) {
      return getNextPatchHelper(-1, false, currentIndex, validators);
    }

    return -1;
  }

  /**
   * @return the index to the previous patch
   */
  public int getPreviousPatch(int currentIndex, PatchValidator... validators) {
    for (int i = currentIndex - 1; i >= 0; i--) {
      Patch patch = detail.getPatches().get(i);
      if (patch != null && patchIsValid(patch, validators)) {
        return i;
      }
    }

    return -1;
  }

  /**
   * Helper function that returns whether a patch is valid or not
   *
   * @param patch
   * @param validators
   * @return whether the patch is valid based on the validators
   */
  private boolean patchIsValid(Patch patch, PatchValidator... validators) {
    for (PatchValidator v : validators) {
      if (!v.isValid(patch)) {
        return false;
      }
    }
    return true;
  }
}
