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

library class_tree_element;

import 'dart:html';
import 'dart:async';
import 'package:observatory/models.dart' as M;
import 'package:observatory/src/elements/class_ref.dart';
import 'package:observatory/src/elements/containers/virtual_tree.dart';
import 'package:observatory/src/elements/helpers/nav_bar.dart';
import 'package:observatory/src/elements/helpers/nav_menu.dart';
import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory/src/elements/helpers/custom_element.dart';
import 'package:observatory/src/elements/nav/isolate_menu.dart';
import 'package:observatory/src/elements/nav/notify.dart';
import 'package:observatory/src/elements/nav/top_menu.dart';
import 'package:observatory/src/elements/nav/vm_menu.dart';

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

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

  late M.VM _vm;
  late M.IsolateRef _isolate;
  late M.EventRepository _events;
  late M.NotificationRepository _notifications;
  late M.ClassRepository _classes;
  M.Class? _object;
  final _subclasses = <String, Iterable<M.Class>>{};
  final _mixins = <String, List<M.Instance>?>{};

  factory ClassTreeElement(
      M.VM vm,
      M.IsolateRef isolate,
      M.EventRepository events,
      M.NotificationRepository notifications,
      M.ClassRepository classes,
      {RenderingQueue? queue}) {
    assert(vm != null);
    assert(isolate != null);
    assert(events != null);
    assert(notifications != null);
    assert(classes != null);
    ClassTreeElement e = new ClassTreeElement.created();
    e._r = new RenderingScheduler<ClassTreeElement>(e, queue: queue);
    e._vm = vm;
    e._isolate = isolate;
    e._events = events;
    e._notifications = notifications;
    e._classes = classes;
    return e;
  }

  ClassTreeElement.created() : super.created('class-tree');

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

  @override
  void detached() {
    super.detached();
    children = <Element>[];
    _r.disable(notify: true);
  }

  VirtualTreeElement? _tree;

  void render() {
    children = <Element>[
      navBar(<Element>[
        new NavTopMenuElement(queue: _r.queue).element,
        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
        navMenu('class hierarchy'),
        new NavNotifyElement(_notifications, queue: _r.queue).element
      ]),
      new DivElement()
        ..classes = ['content-centered']
        ..children = <Element>[
          new HeadingElement.h1()
            ..text = 'Class Hierarchy (${_subclasses.length})',
          new BRElement(),
          new HRElement(),
          _object == null
              ? (new HeadingElement.h2()..text = 'Loading...')
              : _createTree()
        ]
    ];
  }

  Element _createTree() {
    _tree = new VirtualTreeElement(_create, _update, _children,
        items: [_object], search: _search, queue: _r.queue);
    _tree!.expand(_object, autoExpandSingleChildNodes: true);
    return _tree!.element;
  }

  Future _refresh() async {
    _object = null;
    _subclasses.clear();
    _mixins.clear();
    _object = await _register(await _classes.getObject(_isolate));
    _r.dirty();
  }

  Future<M.Class> _register(M.Class cls) async {
    _subclasses[cls.id!] = await Future.wait(
        (await Future.wait(cls.subclasses!.map(_getActualChildrens)))
            .expand((f) => f)
            .map(_register));
    return cls;
  }

  Future<Iterable<M.Class>> _getActualChildrens(M.ClassRef ref) async {
    var cls = await _classes.get(_isolate, ref.id!);
    if (cls.isPatch!) {
      return const [];
    }
    if (cls.mixin == null) {
      return [cls];
    }
    return (await Future.wait(cls.subclasses!.map(_getActualChildrens)))
        .expand((f) => f)
          ..forEach((subcls) {
            _mixins[subcls.id!] = (_mixins[subcls.id!] ?? [])
              ..add(cls.mixin as M.Instance);
          });
  }

  static HtmlElement _create(toggle) {
    return new DivElement()
      ..classes = ['class-tree-item']
      ..children = <Element>[
        new SpanElement()..classes = ['lines'],
        new ButtonElement()
          ..classes = ['expander']
          ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
        new SpanElement()..classes = ['name']
      ];
  }

  void _update(HtmlElement el, classDynamic, int index) {
    M.Class cls = classDynamic;
    virtualTreeUpdateLines(el.children[0] as SpanElement, index);
    if (cls.subclasses!.isEmpty) {
      el.children[1].text = '';
    } else {
      el.children[1].text = _tree!.isExpanded(cls) ? '▼' : '►';
    }
    el.children[2].children = <Element>[
      new ClassRefElement(_isolate, cls, queue: _r.queue).element
    ];
    if (_mixins[cls.id] != null) {
      el.children[2].children.addAll(_createMixins(_mixins[cls.id]!));
    }
  }

  bool _search(Pattern pattern, classDynamic) {
    M.Class cls = classDynamic;
    return cls.name!.contains(pattern);
  }

  List<Element> _createMixins(List<M.Instance> types) {
    final children = types
        .expand((type) => <Element>[
              new SpanElement()..text = ', ',
              type.typeClass == null
                  ? (new SpanElement()..text = type.name!.split('<').first)
                  : new ClassRefElement(_isolate, type.typeClass!,
                          queue: _r.queue)
                      .element
            ])
        .toList();
    children.first.text = ' with ';
    return children;
  }

  Iterable<M.Class> _children(classDynamic) {
    M.Class cls = classDynamic;
    return _subclasses[cls.id]!;
  }
}
