// Copyright (c) 2013, 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 eval_box_element;

import 'dart:html';
import 'dart:async';
import 'package:observatory/models.dart' as M;
import 'package:observatory/src/elements/helpers/any_ref.dart';
import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory/src/elements/helpers/custom_element.dart';
import 'package:observatory/src/elements/instance_ref.dart';

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

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

  late M.IsolateRef _isolate;
  late M.ObjectRef _context;
  late M.ObjectRepository _objects;
  late M.EvalRepository _eval;
  final _results = <_ExpressionDescription>[];
  String? _expression = '';
  late bool _multiline;
  late Iterable<String> _quickExpressions;

  M.IsolateRef get isolate => _isolate;
  M.ObjectRef get context => _context;

  factory EvalBoxElement(M.IsolateRef isolate, M.ObjectRef context,
      M.ObjectRepository objects, M.EvalRepository eval,
      {bool multiline: false,
      Iterable<String> quickExpressions: const [],
      RenderingQueue? queue}) {
    assert(isolate != null);
    assert(context != null);
    assert(objects != null);
    assert(eval != null);
    assert(multiline != null);
    assert(quickExpressions != null);
    EvalBoxElement e = new EvalBoxElement.created();
    e._r = new RenderingScheduler<EvalBoxElement>(e, queue: queue);
    e._isolate = isolate;
    e._context = context;
    e._objects = objects;
    e._eval = eval;
    e._multiline = multiline;
    e._quickExpressions = new List.unmodifiable(quickExpressions);
    return e;
  }

  EvalBoxElement.created() : super.created('eval-box');

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

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

  void render() {
    children = <Element>[
      new DivElement()
        ..classes = ['quicks']
        ..children = _quickExpressions
            .map<Element>((q) => new ButtonElement()
              ..text = q
              ..onClick.listen((_) {
                _expression = q;
                _run();
              }))
            .toList(),
      new DivElement()
        ..classes = ['heading']
        ..children = <Element>[
          new FormElement()
            ..autocomplete = 'on'
            ..children = <Element>[
              _multiline ? _createEvalTextArea() : _createEvalTextBox(),
              new SpanElement()
                ..classes = ['buttons']
                ..children = <Element>[
                  _createEvalButton(),
                  _createMultilineCheckbox(),
                  new SpanElement()..text = 'Multi-line'
                ]
            ]
        ],
      new TableElement()
        ..children = _results.reversed
            .map<Element>((result) => new TableRowElement()
              ..children = <Element>[
                new TableCellElement()
                  ..classes = ['historyExpr']
                  ..children = <Element>[
                    new ButtonElement()
                      ..text = result.expression
                      ..onClick.listen((_) {
                        _expression = result.expression;
                        _r.dirty();
                      })
                  ],
                new TableCellElement()
                  ..classes = ['historyValue']
                  ..children = <Element>[
                    result.isPending
                        ? (new SpanElement()..text = 'Pending...')
                        : anyRef(_isolate, result.value, _objects,
                            queue: _r.queue)
                  ],
                new TableCellElement()
                  ..classes = ['historyDelete']
                  ..children = <Element>[
                    new ButtonElement()
                      ..text = '✖ Remove'
                      ..onClick.listen((_) {
                        _results.remove(result);
                        _r.dirty();
                      })
                  ]
              ])
            .toList()
    ];
  }

  TextAreaElement _createEvalTextArea() {
    var area = new TextAreaElement()
      ..classes = ['textbox']
      ..placeholder = 'evaluate an expression'
      ..value = _expression
      ..onKeyUp.where((e) => e.key == '\n').listen((e) {
        e.preventDefault();
        _run();
      });
    area.onInput.listen((e) {
      _expression = area.value;
    });
    return area;
  }

  TextInputElement _createEvalTextBox() {
    _expression = (_expression ?? '').split('\n')[0];
    var textbox = new TextInputElement()
      ..classes = ['textbox']
      ..placeholder = 'evaluate an expression'
      ..value = _expression
      ..onKeyUp.where((e) => e.key == '\n').listen((e) {
        e.preventDefault();
        _run();
      });
    textbox.onInput.listen((e) {
      _expression = textbox.value;
    });
    return textbox;
  }

  ButtonElement _createEvalButton() {
    final button = new ButtonElement()
      ..text = 'Evaluate'
      ..onClick.listen((e) {
        e.preventDefault();
        _run();
      });
    return button;
  }

  CheckboxInputElement _createMultilineCheckbox() {
    final checkbox = new CheckboxInputElement()..checked = _multiline;
    checkbox.onClick.listen((e) {
      e.preventDefault();
      _multiline = checkbox.checked!;
      _r.dirty();
    });
    return checkbox;
  }

  Future _run() async {
    final expression = _expression;
    if (expression == null || expression.isEmpty) return;
    _expression = null;
    final result = new _ExpressionDescription.pending(expression);
    _results.add(result);
    _r.dirty();
    final index = _results.indexOf(result);
    _results[index] = new _ExpressionDescription(
        expression, await _eval.evaluate(_isolate, _context, expression));
    _r.dirty();
  }
}

class _ExpressionDescription {
  final String expression;
  final M.ObjectRef? value;
  bool get isPending => value == null;

  _ExpressionDescription(this.expression, this.value);
  _ExpressionDescription.pending(this.expression) : value = null;
}
