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

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.common.data.ChangeDetail;
import com.google.gerrit.reviewdb.PatchSet;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwtexpui.globalkey.client.GlobalKey;
import com.google.gwtexpui.globalkey.client.KeyCommand;
import com.google.gwtexpui.globalkey.client.KeyCommandSet;

import java.util.HashMap;
import java.util.List;

/**
 * Composite that displays the patch sets of a change. This composite ensures
 * that keyboard navigation to each changed file in all patch sets is possible.
 */
public class PatchSetsBlock extends Composite {

  private final HashMap<PatchSet.Id, PatchSetComplexDisclosurePanel> patchSetPanels =
      new HashMap<PatchSet.Id, PatchSetComplexDisclosurePanel>();

  private final ChangeScreen parent;
  private final FlowPanel body;
  private HandlerRegistration regNavigation;

  /**
   * the patch set id of the patch set for which is the keyboard navigation is
   * currently enabled
   */
  private PatchSet.Id activePatchSetId;

  /** the patch set id of the current (latest) patch set */
  private PatchSet.Id currentPatchSetId;

  /** Patch sets on this change, in order. */
  private List<PatchSet> patchSets;

  PatchSetsBlock(final ChangeScreen parent) {
    this.parent = parent;
    body = new FlowPanel();
    initWidget(body);
  }

  /** Adds UI elements for each patch set of the given change to this composite. */
  public void display(final ChangeDetail detail) {
    clear();

    final PatchSet currps = detail.getCurrentPatchSet();
    currentPatchSetId = currps.getId();
    patchSets = detail.getPatchSets();

    for (final PatchSet ps : patchSets) {
      if (ps == currps) {
        add(new PatchSetComplexDisclosurePanel(parent, detail, detail
            .getCurrentPatchSetDetail()));
      } else {
        add(new PatchSetComplexDisclosurePanel(parent, detail, ps));
      }
    }
  }

  private void clear() {
    setRegisterKeys(false);
    body.clear();
    patchSetPanels.clear();
  }

  /**
   * Adds the given patch set panel to this composite and ensures that handler
   * to activate / deactivate keyboard navigation for the patch set panel are
   * registered.
   */
  private void add(final PatchSetComplexDisclosurePanel patchSetPanel) {
    body.add(patchSetPanel);

    final PatchSet.Id id = patchSetPanel.getPatchSet().getId();
    ActivationHandler activationHandler = new ActivationHandler(id);
    patchSetPanel.addOpenHandler(activationHandler);
    patchSetPanel.addClickHandler(activationHandler);
    patchSetPanels.put(id, patchSetPanel);
  }

  public void setRegisterKeys(final boolean on) {
    if (on) {
      KeyCommandSet keysNavigation =
          new KeyCommandSet(Gerrit.C.sectionNavigation());
      keysNavigation.add(new PreviousPatchSetKeyCommand(0, 'p', Util.C
          .previousPatchSet()));
      keysNavigation.add(new NextPatchSetKeyCommand(0, 'n', Util.C
          .nextPatchSet()));
      regNavigation = GlobalKey.add(this, keysNavigation);
      if (activePatchSetId != null) {
        activate(activePatchSetId);
      } else {
        activate(currentPatchSetId);
      }
    } else {
      if (regNavigation != null) {
        regNavigation.removeHandler();
        regNavigation = null;
      }
      deactivate();
    }
  }

  @Override
  protected void onUnload() {
    setRegisterKeys(false);
    super.onUnload();
  }

  /**
   * Activates keyboard navigation for the patch set panel that displays the
   * patch set with the given patch set id.
   * The keyboard navigation for the previously active patch set panel is
   * automatically deactivated.
   * This method also ensures that the current row is only highlighted in the
   * table of the active patch set panel.
   */
  private void activate(final PatchSet.Id patchSetId) {
    if (!patchSetId.equals(activePatchSetId)) {
      deactivate();
      PatchSetComplexDisclosurePanel patchSetPanel =
          patchSetPanels.get(patchSetId);
      patchSetPanel.setOpen(true);
      patchSetPanel.setActive(true);
      activePatchSetId = patchSetId;
    }
  }

  /** Deactivates the keyboard navigation for the currently active patch set panel. */
  private void deactivate() {
    if (activePatchSetId != null) {
      PatchSetComplexDisclosurePanel patchSetPanel =
          patchSetPanels.get(activePatchSetId);
      patchSetPanel.setActive(false);
      activePatchSetId = null;
    }
  }

  public PatchSet getCurrentPatchSet() {
    PatchSetComplexDisclosurePanel patchSetPanel =
        patchSetPanels.get(currentPatchSetId);
    if (patchSetPanel != null) {
      return patchSetPanel.getPatchSet();
    } else {
      return null;
    }
  }

  private int indexOf(PatchSet.Id id) {
    for (int i = 0; i < patchSets.size(); i++) {
      if (patchSets.get(i).getId().equals(id)) {
        return i;
      }
    }
    return -1;
  }

  private class ActivationHandler implements OpenHandler<DisclosurePanel>,
      ClickHandler {

    private final PatchSet.Id patchSetId;

    ActivationHandler(PatchSet.Id patchSetId) {
      this.patchSetId = patchSetId;
    }

    @Override
    public void onOpen(OpenEvent<DisclosurePanel> event) {
      // when a patch set panel is opened by the user
      // it should automatically become active
      activate(patchSetId);
    }

    @Override
    public void onClick(ClickEvent event) {
      // when a user clicks on a patch table the corresponding
      // patch set panel should automatically become active
      activate(patchSetId);
    }

  }

  public class PreviousPatchSetKeyCommand extends KeyCommand {
    public PreviousPatchSetKeyCommand(int mask, char key, String help) {
      super(mask, key, help);
    }

    @Override
    public void onKeyPress(final KeyPressEvent event) {
      int index = indexOf(activePatchSetId) - 1;
      if (0 <= index) {
        activate(patchSets.get(index).getId());
      }
    }
  }

  public class NextPatchSetKeyCommand extends KeyCommand {
    public NextPatchSetKeyCommand(int mask, char key, String help) {
      super(mask, key, help);
    }

    @Override
    public void onKeyPress(final KeyPressEvent event) {
      int index = indexOf(activePatchSetId) + 1;
      if (index < patchSets.size()) {
        activate(patchSets.get(index).getId());
      }
    }
  }
}
