// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// @dart = 2.9

part of view;

typedef void SelectHandler(String menuText);

/**
 * This implements a horizontal menu bar with a sliding triangle arrow
 * that points at the currently selected item.
 */
class SliderMenu extends View {
  static const int TRIANGLE_WIDTH = 24;

  // currently selected menu item
  Element selectedItem;

  // This holds the element where a touchstart occured.  (This is set
  // in touchstart, and cleared in touchend.)  If this is null, then a
  // touch operation is not in progress.
  // TODO(mattsh) - move this to a touch mixin
  Element touchItem;

  /**
   * Callback function that we call when the user chooses something from
   * the menu.  This is passed the menu item text.
   */
  SelectHandler onSelect;

  List<String> _menuItems;

  SliderMenu(this._menuItems, this.onSelect);

  Element render() {
    // Create a div for each menu item.
    final items = new StringBuffer();
    for (final item in _menuItems) {
      items.write('<div class="sm-item">$item</div>');
    }

    // Create a root node to hold this view.
    return new Element.html('''
        <div class="sm-root">
          <div class="sm-item-box">
            <div class="sm-item-filler"></div>
            $items
            <div class="sm-item-filler"></div>
          </div>
          <div class="sm-slider-box">
            <div class="sm-triangle"></div>
          </div>
        </div>
        ''');
  }

  void enterDocument() {
    // select the first item
    // todo(jacobr): too much actual work is performed in enterDocument.
    // Ideally, enterDocument should do nothing more than redecorate a view
    // and perhaps calculating the correct child sizes for edge cases that
    // cannot be handled by the browser layout engine.
    selectItem(node.querySelector('.sm-item'), false);

    // TODO(mattsh), abstract this somehow into a touch click mixin
    if (Device.supportsTouch) {
      node.onTouchStart.listen((event) {
        touchItem = itemOfTouchEvent(event);
        if (touchItem != null) {
          selectItemText(touchItem);
        }
        event.preventDefault();
      });
      node.onTouchEnd.listen((event) {
        if (touchItem != null) {
          if (itemOfTouchEvent(event) == touchItem) {
            selectItem(touchItem, true);
          } else {
            // the Touch target is somewhere other where than the touchstart
            // occured, so revert the selected menu text back to where it was
            // before the touchstart,
            selectItemText(selectedItem);
          }
          // touch operation has ended
          touchItem = null;
        }
        event.preventDefault();
      });
    } else {
      node.onClick.listen((event) => selectItem(event.target, true));
    }

    window.onResize.listen((Event event) => updateIndicator(false));
  }

  /**
   * Walks the parent chain of the first Touch target to find the first ancestor
   * that has sm-item class.
   */
  Element itemOfTouchEvent(event) {
    Node node = event.changedTouches[0].target;
    return itemOfNode(node);
  }

  Element itemOfNode(Node node) {
    // TODO(jmesserly): workaround for bug 5399957, document.parent == document
    while (node != null && node != document) {
      if (node is Element) {
        Element element = node;
        if (element.classes.contains('sm-item')) {
          return element;
        }
      }
      node = node.parent;
    }
    return null;
  }

  void selectItemText(Element item) {
    // unselect all menu items
    for (final sliderItem in node.querySelectorAll('.sm-item')) {
      sliderItem.classes.remove('sel');
    }

    // select the item the user clicked on
    item.classes.add('sel');
  }

  void selectItem(Element item, bool animate) {
    if (!item.classes.contains('sm-item')) {
      return;
    }

    selectedItem = item;
    selectItemText(item);
    updateIndicator(animate);
    onSelect(item.text);
  }

  void selectNext(bool animate) {
    final result = node.querySelector('.sm-item.sel').nextElementSibling;
    if (result != null) {
      selectItem(result, animate);
    }
  }

  void selectPrevious(bool animate) {
    final result = node.querySelector('.sm-item.sel').previousElementSibling;
    if (result != null) {
      selectItem(result, animate);
    }
  }

  /**
   * animate - if true, then animate the movement of the triangle slider
   */
  void updateIndicator(bool animate) {
    if (selectedItem != null) {
      // calculate where we want to put the triangle
      scheduleMicrotask(() {
        num x = selectedItem.offset.left +
            selectedItem.offset.width / 2 -
            TRIANGLE_WIDTH / 2;
        _moveIndicator(x, animate);
      });
    } else {
      _moveIndicator(0, animate);
    }
  }

  void _moveIndicator(num x, bool animate) {
    // find the slider filler (the div element to the left of the
    // triangle) set its width the push the triangle to where we want it.
    String duration = animate ? '.3s' : '0s';
    final triangle = node.querySelector('.sm-triangle');
    triangle.style.transitionDuration = duration;
    FxUtil.setWebkitTransform(triangle, x, 0);
  }
}
