// Copyright (C) 2009 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.gwtexpui.globalkey.client;

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.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusPanel;
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.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import com.google.gwtexpui.user.client.PluginSafePopupPanel;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;


public class KeyHelpPopup extends PluginSafePopupPanel implements
    KeyPressHandler, KeyDownHandler {
  private final FocusPanel focus;

  public KeyHelpPopup() {
    super(true/* autohide */, true/* modal */);
    setStyleName(KeyResources.I.css().helpPopup());

    final Anchor closer = new Anchor(KeyConstants.I.closeButton());
    closer.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        hide();
      }
    });

    final Grid header = new Grid(1, 3);
    header.setStyleName(KeyResources.I.css().helpHeader());
    header.setText(0, 0, KeyConstants.I.keyboardShortcuts());
    header.setWidget(0, 2, closer);

    final CellFormatter fmt = header.getCellFormatter();
    fmt.addStyleName(0, 1, KeyResources.I.css().helpHeaderGlue());
    fmt.setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_RIGHT);

    final Grid lists = new Grid(0, 7);
    lists.setStyleName(KeyResources.I.css().helpTable());
    populate(lists);
    lists.getCellFormatter().addStyleName(0, 3,
        KeyResources.I.css().helpTableGlue());

    final FlowPanel body = new FlowPanel();
    body.add(header);
    DOM.appendChild(body.getElement(), DOM.createElement("hr"));
    body.add(lists);

    focus = new FocusPanel(body);
    focus.getElement().getStyle().setProperty("outline", "0px");
    focus.getElement().setAttribute("hideFocus", "true");
    focus.addKeyPressHandler(this);
    focus.addKeyDownHandler(this);
    add(focus);
  }

  @Override
  public void setVisible(final boolean show) {
    super.setVisible(show);
    if (show) {
      focus.setFocus(true);
    }
  }

  @Override
  public void onKeyPress(final KeyPressEvent event) {
    if (KeyCommandSet.toMask(event) == ShowHelpCommand.INSTANCE.keyMask) {
      // Block the '?' key from triggering us to show right after
      // we just hide ourselves.
      //
      event.stopPropagation();
      event.preventDefault();
    }
    hide();
  }

  @Override
  public void onKeyDown(final KeyDownEvent event) {
    if (event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) {
      hide();
    }
  }

  private void populate(final Grid lists) {
    int end[] = new int[5];
    int column = 0;
    for (final KeyCommandSet set : combinedSetsByName()) {
      int row = end[column];
      row = formatGroup(lists, row, column, set);
      end[column] = row;
      if (column == 0) {
        column = 4;
      } else {
        column = 0;
      }
    }
  }

  /**
   * @return an ordered collection of KeyCommandSet, combining sets which share
   *         the same name, so that each set name appears at most once.
   */
  private static Collection<KeyCommandSet> combinedSetsByName() {
    final LinkedHashMap<String, KeyCommandSet> byName =
        new LinkedHashMap<String, KeyCommandSet>();
    for (final KeyCommandSet set : GlobalKey.active.all.getSets()) {
      KeyCommandSet v = byName.get(set.getName());
      if (v == null) {
        v = new KeyCommandSet(set.getName());
        byName.put(v.getName(), v);
      }
      v.add(set);
    }
    return byName.values();
  }

  private int formatGroup(final Grid lists, int row, final int col,
      final KeyCommandSet set) {
    if (set.isEmpty()) {
      return row;
    }

    if (lists.getRowCount() < row + 1) {
      lists.resizeRows(row + 1);
    }
    lists.setText(row, col + 2, set.getName());
    lists.getCellFormatter().addStyleName(row, col + 2,
        KeyResources.I.css().helpGroup());
    row++;

    return formatKeys(lists, row, col, set, null);
  }

  private int formatKeys(final Grid lists, int row, final int col,
      final KeyCommandSet set, final SafeHtml prefix) {
    final CellFormatter fmt = lists.getCellFormatter();
    final List<KeyCommand> keys = sort(set);
    if (lists.getRowCount() < row + keys.size()) {
      lists.resizeRows(row + keys.size());
    }

    Map<KeyCommand, Integer> rows = new HashMap<KeyCommand, Integer>();
    FORMAT_KEYS: for (int i = 0; i < keys.size(); i++) {
      final KeyCommand k = keys.get(i);
      if (rows.containsKey(k)) {
        continue;
      }

      if (k instanceof CompoundKeyCommand) {
        final SafeHtmlBuilder b = new SafeHtmlBuilder();
        b.append(k.describeKeyStroke());
        row = formatKeys(lists, row, col, ((CompoundKeyCommand) k).getSet(), b);
        continue;
      }

      for (int prior = 0; prior < i; prior++) {
        if (KeyCommand.same(keys.get(prior), k)) {
          final int r = rows.get(keys.get(prior));
          final SafeHtmlBuilder b = new SafeHtmlBuilder();
          b.append(SafeHtml.get(lists, r, col + 0));
          b.append(" ");
          b.append(KeyConstants.I.orOtherKey());
          b.append(" ");
          if (prefix != null) {
            b.append(prefix);
            b.append(" ");
            b.append(KeyConstants.I.thenOtherKey());
            b.append(" ");
          }
          b.append(k.describeKeyStroke());
          SafeHtml.set(lists, r, col + 0, b);
          rows.put(k, r);
          continue FORMAT_KEYS;
        }
      }

      SafeHtmlBuilder b = new SafeHtmlBuilder();
      String t = k.getHelpText();
      if (prefix != null) {
        b.append(prefix);
        b.append(" ");
        b.append(KeyConstants.I.thenOtherKey());
        b.append(" ");
      }
      b.append(k.describeKeyStroke());
      if (k.sibling != null) {
        b.append(" / ").append(k.sibling.describeKeyStroke());
        t += " / " + k.sibling.getHelpText();
        rows.put(k.sibling, row);
      }
      SafeHtml.set(lists, row, col + 0, b);
      lists.setText(row, col + 1, ":");
      lists.setText(row, col + 2, t);
      rows.put(k, row);

      fmt.addStyleName(row, col + 0, KeyResources.I.css().helpKeyStroke());
      fmt.addStyleName(row, col + 1, KeyResources.I.css().helpSeparator());
      row++;
    }

    return row;
  }

  private List<KeyCommand> sort(final KeyCommandSet set) {
    final List<KeyCommand> keys = new ArrayList<KeyCommand>(set.getKeys());
    Collections.sort(keys, new Comparator<KeyCommand>() {
      @Override
      public int compare(KeyCommand arg0, KeyCommand arg1) {
        return arg0.getHelpText().compareTo(arg1.getHelpText());
      }
    });
    return keys;
  }
}
