// Copyright (c) 2016, 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.

import 'dart:async';
import 'dart:html';
import 'dart:collection';
import 'dart:math' as Math;
import 'package:observatory/src/elements/containers/virtual_collection.dart';
import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory/src/elements/helpers/custom_element.dart';

typedef HtmlElement VirtualTreeCreateCallback(
    toggle({bool autoToggleSingleChildNodes, bool autoToggleWholeTree}));
typedef void VirtualTreeUpdateCallback(HtmlElement el, dynamic item, int depth);
typedef Iterable<dynamic> VritualTreeGetChildrenCallback(dynamic value);
typedef bool VirtualTreeSearchCallback(Pattern pattern, dynamic item);

void virtualTreeUpdateLines(SpanElement element, int n) {
  n = Math.max(0, n);
  while (element.children.length > n) {
    element.children.removeLast();
  }
  while (element.children.length < n) {
    element.children.add(new SpanElement());
  }
}

class VirtualTreeElement extends CustomElement implements Renderable {
  late RenderingScheduler<VirtualTreeElement> _r;

  Stream<RenderedEvent<VirtualTreeElement>> get onRendered => _r.onRendered;

  late VritualTreeGetChildrenCallback _children;
  late List _items;
  late List _depths;
  final Set _expanded = new Set();

  List get items => _items;

  set items(Iterable value) {
    _items = new List.unmodifiable(value);
    _expanded.clear();
    _r.dirty();
  }

  factory VirtualTreeElement(VirtualTreeCreateCallback create,
      VirtualTreeUpdateCallback update, VritualTreeGetChildrenCallback children,
      {Iterable items: const [],
      VirtualTreeSearchCallback? search,
      RenderingQueue? queue}) {
    assert(create != null);
    assert(update != null);
    assert(children != null);
    assert(items != null);
    VirtualTreeElement e = new VirtualTreeElement.created();
    e._r = new RenderingScheduler<VirtualTreeElement>(e, queue: queue);
    e._children = children;
    e._collection = new VirtualCollectionElement(() {
      var element;
      return element = create((
          {bool autoToggleSingleChildNodes: false,
          bool autoToggleWholeTree: false}) {
        var item = e._collection!.getItemFromElement(element);
        if (e.isExpanded(item)) {
          e.collapse(item,
              autoCollapseWholeTree: autoToggleWholeTree,
              autoCollapseSingleChildNodes: autoToggleSingleChildNodes);
        } else {
          e.expand(item,
              autoExpandWholeTree: autoToggleWholeTree,
              autoExpandSingleChildNodes: autoToggleSingleChildNodes);
        }
      });
    }, (HtmlElement el, dynamic item, int index) {
      update(el, item, e._depths[index]);
    }, search: search, queue: queue);
    e._items = new List.unmodifiable(items);
    return e;
  }

  VirtualTreeElement.created() : super.created('virtual-tree');

  bool isExpanded(item) {
    return _expanded.contains(item);
  }

  void expand(item,
      {bool autoExpandSingleChildNodes: false,
      bool autoExpandWholeTree: false}) {
    if (_expanded.add(item)) _r.dirty();
    if (autoExpandWholeTree) {
      // The tree is potentially very deep, simple recursion can produce a
      // Stack Overflow
      Queue pendingNodes = new Queue();
      pendingNodes.addAll(_children(item));
      while (pendingNodes.isNotEmpty) {
        final item = pendingNodes.removeFirst();
        if (_expanded.add(item)) _r.dirty();
        pendingNodes.addAll(_children(item));
      }
    } else if (autoExpandSingleChildNodes) {
      var children = _children(item);
      while (children.length == 1) {
        _expanded.add(children.first);
        children = _children(children.first);
      }
    }
  }

  void collapse(item,
      {bool autoCollapseSingleChildNodes: false,
      bool autoCollapseWholeTree: false}) {
    if (_expanded.remove(item)) _r.dirty();
    if (autoCollapseWholeTree) {
      // The tree is potentially very deep, simple recursion can produce a
      // Stack Overflow
      Queue pendingNodes = new Queue();
      pendingNodes.addAll(_children(item));
      while (pendingNodes.isNotEmpty) {
        final item = pendingNodes.removeFirst();
        if (_expanded.remove(item)) _r.dirty();
        pendingNodes.addAll(_children(item));
      }
    } else if (autoCollapseSingleChildNodes) {
      var children = _children(item);
      while (children.length == 1) {
        _expanded.remove(children.first);
        children = _children(children.first);
      }
    }
  }

  @override
  attached() {
    super.attached();
    _r.enable();
  }

  @override
  detached() {
    super.detached();
    _r.disable(notify: true);
    children = const [];
  }

  VirtualCollectionElement? _collection;

  void render() {
    if (children.length == 0) {
      children = <Element>[_collection!.element];
    }

    final items = [];
    final depths = new List.filled(_items.length, 0, growable: true);

    {
      final toDo = new Queue();

      toDo.addAll(_items);
      while (toDo.isNotEmpty) {
        final item = toDo.removeFirst();

        items.add(item);
        if (isExpanded(item)) {
          final children = _children(item);
          children
              .toList(growable: false)
              .reversed
              .forEach((c) => toDo.addFirst(c));
          final depth = depths[items.length - 1];
          depths.insertAll(
              items.length, new List.filled(children.length, depth + 1));
        }
      }
    }

    _depths = depths;
    _collection!.items = items;

    _r.waitFor([_collection!.onRendered.first]);
  }
}
