// 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 SelectHandler = void Function(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 occurred.  (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;

  final List<String> _menuItems;

  SliderMenu(this._menuItems, this.onSelect);

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

    // Create a root node to hold this view.
    return 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>
        ''');
  }

  @override
  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
            // occurred, 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);
  }
}
