// Copyright (C) 2010 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.Gerrit;
import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.info.WebLinkInfo;
import com.google.gerrit.client.ui.ChangeLink;
import com.google.gerrit.client.ui.InlineHyperlink;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwtexpui.globalkey.client.KeyCommand;
import com.google.gwtexpui.globalkey.client.KeyCommandSet;
import com.google.gwtexpui.safehtml.client.SafeHtml;

import java.util.List;

class NavLinks extends Composite {
  public enum Nav {
    PREV (0, '[', PatchUtil.C.previousFileHelp(), 0),
    NEXT (3, ']', PatchUtil.C.nextFileHelp(), 1);

    public int col;      // Table Cell column to display link in
    public int key;      // key code shortcut to activate link
    public String help;  // help string for '?' popup
    public int cmd;      // index into cmds array

    Nav(int c, int k, String h, int i) {
      this.col = c;
      this.key = k;
      this.help = h;
      this.cmd = i;
    }
  }

  private final PatchSet.Id patchSetId;
  private final KeyCommandSet keys;
  private final Grid table;

  private KeyCommand[] cmds = new KeyCommand[2];

  NavLinks(KeyCommandSet kcs, PatchSet.Id forPatch) {
    patchSetId = forPatch;
    keys = kcs;
    table = new Grid(1, 4);
    initWidget(table);

    final CellFormatter fmt = table.getCellFormatter();
    table.setStyleName(Gerrit.RESOURCES.css().sideBySideScreenLinkTable());
    fmt.setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_LEFT);
    fmt.setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_CENTER);
    fmt.setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_RIGHT);
    fmt.setHorizontalAlignment(0, 3, HasHorizontalAlignment.ALIGN_RIGHT);

    final ChangeLink up = new ChangeLink("", patchSetId);
    SafeHtml.set(up, SafeHtml.asis(Util.C.upToChangeIconLink()));
    table.setWidget(0, 1, up);
  }

  void display(int patchIndex, PatchTable fileList,
      List<InlineHyperlink> links, List<WebLinkInfo> webLinks) {
    if (fileList != null) {
      setupNav(Nav.PREV, fileList.getPreviousPatchLink(patchIndex));
      setupNav(Nav.NEXT, fileList.getNextPatchLink(patchIndex));
    } else {
      setupNav(Nav.PREV, null);
      setupNav(Nav.NEXT, null);
    }

    FlowPanel linkPanel = new FlowPanel();
    linkPanel.setStyleName(Gerrit.RESOURCES.css().linkPanel());
    for (InlineHyperlink link : links) {
      linkPanel.add(link);
    }
    for (WebLinkInfo webLink : webLinks) {
      linkPanel.add(webLink.toAnchor());
    }
    table.setWidget(0, 2, linkPanel);
  }

  protected void setupNav(final Nav nav, final InlineHyperlink link) {

    /* setup the cells */
    if (link != null) {
      link.addStyleName(Gerrit.RESOURCES.css().nowrap());
      table.setWidget(0, nav.col, link);
    } else {
      table.clearCell(0, nav.col);
    }

    /* setup the keys */
    if (keys != null) {

      if (cmds[nav.cmd] != null) {
        keys.remove(cmds[nav.cmd]);
      }

      if (link != null) {
        cmds[nav.cmd] = new KeyCommand(0, nav.key, nav.help) {
          @Override
          public void onKeyPress(KeyPressEvent event) {
            link.go();
          }
        };
      } else {
        cmds[nav.cmd] = new UpToChangeCommand(patchSetId, 0, nav.key);
      }

      keys.add(cmds[nav.cmd]);
    }
  }
}
