// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// TODO(jacobr): make this class production quality. It is missing some
// important edge cases.

/// Use this library to render an inspector tree to HTML elements instead of
/// canvas.
library inspector_tree_html;

import 'dart:html';

import 'package:meta/meta.dart';

import '../ui/elements.dart';
import '../ui/fake_flutter/fake_flutter.dart';
import '../ui/flutter_html_shim.dart';
import '../ui/html_icon_renderer.dart';
import '../ui/icons.dart';
import 'diagnostics_node.dart';
import 'inspector_service.dart';
import 'inspector_text_styles.dart';
import 'inspector_tree.dart';
import 'inspector_tree_web.dart';

abstract class HtmlPaintEntry extends PaintEntry {
  void paint(Element parent);

  Element element;
}

class IconPaintEntry extends HtmlPaintEntry {
  IconPaintEntry({
    @required this.iconRenderer,
  });

  @override
  Icon get icon => iconRenderer.icon;

  final HtmlIconRenderer iconRenderer;

  @override
  void paint(Element parent) {
    element = iconRenderer.createElement();
    parent.append(element);
  }

  @override
  void attach(InspectorTree owner) {
    // The browser handles painting images when they are available so we don't
    // have to do anything.
  }
}

class HtmlTextPaintEntry extends HtmlPaintEntry {
  HtmlTextPaintEntry({
    @required this.text,
    @required this.color,
    @required this.font,
  });

  final String text;
  final String color;
  final String font;

  @override
  Icon get icon => null;

  @override
  void paint(Element parent) {
    element = Element.span()..text = text;
    if (color != null) {
      element.style.color = color;
    }
    if (font != null) {
      element.style.font = font;
    }
    parent.append(element);
  }
}

class InspectorTreeNodeRenderHtmlBuilder
    extends InspectorTreeNodeRenderBuilder<InspectorTreeNodeHtmlRender> {
  InspectorTreeNodeRenderHtmlBuilder({
    @required DiagnosticLevel level,
    @required DiagnosticsTreeStyle treeStyle,
    @required this.allowWrap,
  }) : super(level: level, treeStyle: treeStyle);

  TextStyle lastStyle;
  String font;
  String color;
  final bool allowWrap;
  final List<HtmlPaintEntry> _entries = [];

  @override
  void appendText(String text, TextStyle textStyle) {
    if (text == null || text.isEmpty) {
      return;
    }
    if (textStyle != lastStyle) {
      if (textStyle.color != lastStyle?.color) {
        if (textStyle.color == regular.color) {
          color = null;
        } else {
          color = colorToCss(textStyle.color);
        }
      }
      if (textStyle == regular) {
        font = null;
      } else {
        font = fontStyleToCss(textStyle);
      }
      lastStyle = textStyle;
    }
    _entries.add(HtmlTextPaintEntry(text: text, color: color, font: font));
  }

  @override
  void addIcon(Icon icon) {
    _entries.add(IconPaintEntry(iconRenderer: getIconRenderer(icon)));
  }

  @override
  InspectorTreeNodeHtmlRender build() {
    // The html renderer does not know what its size is.
    final classes = [
      'inspector-level-${diagnosticLevelToName[level]}',
      'inspector-style-${treeStyleToName[treeStyle]}',
    ];
    if (!allowWrap) {
      classes.add('inspector-no-wrap');
    }
    return InspectorTreeNodeHtmlRender(_entries, const Size(0, 0), classes);
  }
}

class InspectorTreeNodeHtmlRender
    extends InspectorTreeNodeRender<HtmlPaintEntry> {
  InspectorTreeNodeHtmlRender(
      List<HtmlPaintEntry> entries, Size size, this.cssClasses)
      : super(entries, size);

  final List<String> cssClasses;

  void paint(Element container) {
    container.classes.addAll(cssClasses);
    element = container;
    for (var entry in entries) {
      entry.paint(container);
    }
  }

  Element element;

  @override
  PaintEntry hitTest(Offset location) {
    // TODO(jacobr): consider removing this method from the base class.
    throw 'Not yet supported by HTML tree';
  }
}

class InspectorTreeNodeHtml extends InspectorTreeNode {
  @override
  InspectorTreeNodeRenderBuilder createRenderBuilder() {
    return InspectorTreeNodeRenderHtmlBuilder(
      level: diagnostic.level,
      treeStyle: diagnostic.style,
      allowWrap: diagnostic.allowWrap,
    );
  }
}

class InspectorTreeHtml extends InspectorTree implements InspectorTreeWeb {
  InspectorTreeHtml({
    @required bool summaryTree,
    @required FlutterTreeType treeType,
    NodeAddedCallback onNodeAdded,
    VoidCallback onSelectionChange,
    TreeEventCallback onExpand,
    TreeHoverEventCallback onHover,
  })  : _container = div(c: 'inspector-tree-html'),
        super(
          summaryTree: summaryTree,
          treeType: treeType,
          onNodeAdded: onNodeAdded,
          onSelectionChange: onSelectionChange,
          onExpand: onExpand,
          onHover: onHover,
        ) {
    _container.onClick.listen(onMouseClick);
    _container.element.onMouseMove.listen(onMouseMove);
    _container.element.onMouseLeave.listen(onMouseLeave);
  }

  InspectorTreeRow _resolveTreeRow(Element e) {
    while (e != null && !e.classes.contains('inspector-tree-row')) {
      e = e.parent;
    }
    if (e == null) {
      return null;
    }
    final parent = e.parent;
    final int index = parent.children.indexOf(e);
    assert(index >= 0 && index < numRows);
    final row = root.getRow(index, selection: selection);
    // TODO(jacobr): figure out why this assert is sometimes failing.
    // final InspectorTreeNodeHtmlRender render = row.node.renderObject;
    // assert(render.element.parent == e);
    return row;
  }

  Icon _resolveIcon(InspectorTreeRow row, Element e) {
    final InspectorTreeNodeHtmlRender render = row?.node?.renderObject;
    if (render == null) {
      return null;
    }
    while (e != null && !e.classes.contains('flutter-icon')) {
      if (e == render.element) {
        return null;
      }
      e = e.parent;
    }
    if (e == null) {
      return null;
    }
    for (var entry in render.entries) {
      if (entry.element == e) {
        return entry.icon;
      }
    }
    return null;
  }

  final CoreElement _container;

  bool _recomputeRows = false;

  @override
  void setState(VoidCallback modifyState) {
    // More closely match Flutter semantics where state is set immediately
    // instead of after a frame.
    modifyState();
    if (!_recomputeRows) {
      _recomputeRows = true;
      window.requestAnimationFrame((_) => _rebuildData());
    }
  }

  void _rebuildData() {
    if (_recomputeRows) {
      _recomputeRows = false;
      if (root == null) {
        _container.clear();
        return;
      }

      final int rowCount = numRows;
      // TODO(jacobr): make this rebuild more incremental.
      _container.clear();
      for (int i = 0; i < rowCount; i++) {
        _container.element.append(paintRow(i, selection: selection));
      }
    }
  }

  void onMouseClick(MouseEvent mouseEvent) {
    final row = _resolveTreeRow(mouseEvent.target);
    if (row == null) {
      return;
    }
    final Icon icon = _resolveIcon(row, mouseEvent.target);
    if (row != null) {
      onTapIcon(row, icon);
    }
  }

  void onMouseMove(MouseEvent mouseEvent) {
    if (onHover != null) {
      // TODO(jacobr): determine the icon
      onHover(_resolveTreeRow(mouseEvent.target)?.node, null);
    }
  }

  void onMouseLeave(MouseEvent mouseEvent) {
    if (onHover != null) {
      onHover(null, null);
    }
  }

  @override
  CoreElement get element => _container;

  @override
  InspectorTreeNode createNode() => InspectorTreeNodeHtml();

  // Horizontal padding is specified by CSS so including it here would throw
  // off calculations.
  @override
  double get horizontalPadding => 0.0;

  Element paintRow(
    int index, {
    @required InspectorTreeNode selection,
  }) {
    try {
      final container = Element.div();
      container.classes.add('inspector-tree-row');
      // Variables incremented as part of painting.
      double currentX = 0;

      final InspectorTreeRow row = root?.getRow(index, selection: selection);
      if (row == null) {
        return container;
      }
      final InspectorTreeNode node = row.node;
      final diagnostic = node.diagnostic;
      // Add an has_property helper on RemoteDiagnosticsNode.
      if (diagnostic != null &&
          diagnostic.name?.isNotEmpty == true &&
          diagnostic.showName &&
          diagnostic.showSeparator &&
          diagnostic.description != null) {
        container.classes.add('property-value');
      }
      // final bool showExpandCollapse = node.showExpandCollapse;
      final InspectorTreeNodeHtmlRender renderObject = node.renderObject;

      // TODO(jacobr): port this code to work for the html renderer to support
      // drawing lines describing the tree. Likely the best way to render this
      // ui is by abusing CSS for drawing borders although we could also consider
      // prerendering some base64 images.
      /*
      bool hasPath = false;
      void _endPath() {
        if (!hasPath) return;
        canvas.stroke();
        hasPath = false;
      }

      void _maybeStart([Color color = Colors.grey]) {
        if (color != currentColor) {
          _endPath();
        }
        if (hasPath) return;
        hasPath = true;
        canvas.beginPath();
        if (currentColor != color) {
          currentColor = color;
          canvas.strokeStyle = colorToCss(color);
        }
        canvas.lineWidth = chartLineStrokeWidth;
      }

      for (int tick in row.ticks) {
        currentX = getDepthIndent(tick) - columnWidth * 0.5;
        if (isVisible(1.0)) {
          final highlight = row.highlightDepth == tick;
          _maybeStart(highlight ? highlightLineColor : defaultTreeLineColor);
          canvas
            ..moveTo(currentX, 0.0)
            ..lineTo(currentX, rowHeight);
        }
      }
      if (row.lineToParent) {
        final highlight = row.highlightDepth == row.depth - 1;
        currentX = getDepthIndent(row.depth - 1) - columnWidth * 0.5;
        final double width = showExpandCollapse ? columnWidth * 0.5 : columnWidth;
        if (isVisible(width)) {
          _maybeStart(highlight ? highlightLineColor : defaultTreeLineColor);
          canvas
            ..moveTo(currentX, 0.0)
            ..lineTo(currentX, rowHeight * 0.5)
            ..lineTo(currentX + width, rowHeight * 0.5);
        }
      }
      _endPath();

      */
      // Render the main row content.
      if (renderObject == null) {
        return container;
      }
      currentX = getDepthIndent(row.depth - 1) - columnWidth;
      if (!row.node.showExpandCollapse) {
        currentX += columnWidth;
      }

      final rowContentContainer = Element.div();
      rowContentContainer.classes.add('inspector-tree-row-content');
      rowContentContainer.style.paddingLeft = '${currentX}px';
      final rowContent = Element.div();
      rowContentContainer.append(rowContent);
      renderObject.paint(rowContent);
      container.append(rowContentContainer);

      // TODO(jacobr): handle row selected backgrounds using CSS classes.
      return container;
    } catch (e, s) {
      print(s);
      return Element.div()..text = 'Error: $e, $s';
    }
  }

  @override
  void animateToTargets(List<InspectorTreeNode> targets) {
    // TODO: implement animateToTargets
    window.requestAnimationFrame((_) {
      for (var target in targets.reversed) {
        final InspectorTreeNodeHtmlRender renderObject = target.renderObject;
        // TODO(jacobr): be smarter about not calling this on all elements.
        renderObject?.element?.scrollIntoView();
      }
    });
  }

  @override
  String get tooltip => element.tooltip;

  @override
  set tooltip(String value) {
    element.tooltip = value;
  }
}
