// Copyright 2013 The Flutter Authors. 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:html' as html;

import 'browser_detection.dart';
import 'dom_renderer.dart';
import 'text_editing/text_editing.dart';

/// The interface required to host a flutter app in the DOM, and its tests.
///
/// Consider this as the intersection in functionality between [html.ShadowRoot]
/// (preferred Flutter rendering method) and [html.Document] (fallback).
///
/// Not to be confused with [html.DocumentOrShadowRoot].
abstract class HostNode {
  /// Retrieves the [html.Element] that currently has focus.
  ///
  /// See:
  /// * [Document.activeElement](https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement)
  html.Element? get activeElement;

  /// Adds a node to the end of the child [nodes] list of this node.
  ///
  /// If the node already exists in this document, it will be removed from its
  /// current parent node, then added to this node.
  ///
  /// This method is more efficient than `nodes.add`, and is the preferred
  /// way of appending a child node.
  ///
  /// See:
  /// * [Node.appendChild](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild)
  html.Node append(html.Node node);

  /// Returns true if this node contains the specified node.
  /// See:
  /// * [Node.contains](https://developer.mozilla.org/en-US/docs/Web/API/Node.contains)
  bool contains(html.Node? other);

  /// Returns the currently wrapped [html.Node].
  html.Node get node;

  /// A modifiable list of this node's children.
  List<html.Node> get nodes;

  /// Finds the first descendant element of this document that matches the
  /// specified group of selectors.
  ///
  /// [selectors] should be a string using CSS selector syntax.
  ///
  /// ```dart
  /// var element1 = document.querySelector('.className');
  /// var element2 = document.querySelector('#id');
  /// ```
  ///
  /// For details about CSS selector syntax, see the
  /// [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
  ///
  /// See:
  /// * [Document.querySelector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector)
  html.Element? querySelector(String selectors);

  /// Finds all descendant elements of this document that match the specified
  /// group of selectors.
  ///
  /// [selectors] should be a string using CSS selector syntax.
  ///
  /// ```dart
  /// var items = document.querySelectorAll('.itemClassName');
  /// ```
  ///
  /// For details about CSS selector syntax, see the
  /// [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
  ///
  /// See:
  /// * [Document.querySelectorAll](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll)
  List<html.Node> querySelectorAll(String selectors);
}

/// A [HostNode] implementation, backed by a [html.ShadowRoot].
///
/// This is the preferred flutter implementation, but it might not be supported
/// by all browsers yet.
///
/// The constructor might throw when calling `attachShadow`, if ShadowDOM is not
/// supported in the current environment. In this case, a fallback [ElementHostNode]
/// should be created instead.
class ShadowDomHostNode implements HostNode {
  late html.ShadowRoot _shadow;

  /// Build a HostNode by attaching a [html.ShadowRoot] to the `root` element.
  ///
  /// This also calls [applyGlobalCssRulesToSheet], defined in dom_renderer.
  ShadowDomHostNode(html.Element root) :
    assert(
    root.isConnected ?? true,
    'The `root` of a ShadowDomHostNode must be connected to the Document object or a ShadowRoot.',
    ) {
    _shadow = root.attachShadow(<String, dynamic>{
      'mode': 'open',
      // This needs to stay false to prevent issues like this:
      // - https://github.com/flutter/flutter/issues/85759
      'delegatesFocus': false,
    });

    final html.StyleElement shadowRootStyleElement = html.StyleElement();
    // The shadowRootStyleElement must be appended to the DOM, or its `sheet` will be null later.
    _shadow.append(shadowRootStyleElement);

    // TODO(dit): Apply only rules for the shadow root
    applyGlobalCssRulesToSheet(
      shadowRootStyleElement.sheet! as html.CssStyleSheet,
      browserEngine: browserEngine,
      hasAutofillOverlay: browserHasAutofillOverlay(),
    );
  }

  @override
  html.Element? get activeElement => _shadow.activeElement;

  @override
  html.Element? querySelector(String selectors) {
    return _shadow.querySelector(selectors);
  }

  @override
  List<html.Node> querySelectorAll(String selectors) {
    return _shadow.querySelectorAll(selectors);
  }

  @override
  html.Node append(html.Node node) {
    return _shadow.append(node);
  }

  @override
  bool contains(html.Node? other) {
    return _shadow.contains(other);
  }

  @override
  html.Node get node => _shadow;

  @override
  List<html.Node> get nodes => _shadow.nodes;
}

/// A [HostNode] implementation, backed by a [html.Element].
///
/// This is a fallback implementation, in case [ShadowDomHostNode] fails when
/// being constructed.
class ElementHostNode implements HostNode {
  late html.Element _element;

  /// Build a HostNode by attaching a child [html.Element] to the `root` element.
  ElementHostNode(html.Element root) {
    _element = html.document.createElement('flt-element-host-node');
    root.append(_element);
  }

  @override
  html.Element? get activeElement => _element.ownerDocument?.activeElement;

  @override
  html.Element? querySelector(String selectors) {
    return _element.querySelector(selectors);
  }

  @override
  List<html.Node> querySelectorAll(String selectors) {
    return _element.querySelectorAll(selectors);
  }

  @override
  html.Node append(html.Node node) {
    return _element.append(node);
  }

  @override
  bool contains(html.Node? other) {
    return _element.contains(other);
  }

  @override
  html.Node get node => _element;

  @override
  List<html.Node> get nodes => _element.nodes;
}
