// 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 'package:ui/ui.dart' as ui;

import '../configuration.dart';
import '../dom.dart';
import '../platform_views/content_manager.dart';
import '../safe_browser_api.dart';
import 'style_manager.dart';

/// Manages DOM elements and the DOM structure for a [ui.FlutterView].
///
/// Here's the general DOM structure of a Flutter View:
///
/// [rootElement] <flutter-view>
///   |
///   +- [platformViewsHost] <flt-glass-pane>
///   |    |
///   |    +- [renderingHost] #shadow-root
///   |    |    |
///   |    |    +- <flt-semantics-placeholder>
///   |    |    |
///   |    |    +- [sceneHost] <flt-scene-host>
///   |    |    |    |
///   |    |    |    +- <flt-scene>
///   |    |    |
///   |    |    +- <style>
///   |    |
///   |    +- ...platform views
///   |
///   +- [textEditingHost] <flt-text-editing-host>
///   |    |
///   |    +- ...text fields
///   |
///   +- [semanticsHost] <flt-semantics-host>
///   |    |
///   |    +- ...semantics nodes
///   |
///   +- <style>
///
class DomManager {
  factory DomManager({required double devicePixelRatio}) {
    final DomElement rootElement = domDocument.createElement(DomManager.flutterViewTagName);
    final DomElement platformViewsHost = domDocument.createElement(DomManager.glassPaneTagName);
    final DomShadowRoot renderingHost = _attachShadowRoot(platformViewsHost);
    final DomElement sceneHost = domDocument.createElement(DomManager.sceneHostTagName);
    final DomElement textEditingHost = domDocument.createElement(DomManager.textEditingHostTagName);
    final DomElement semanticsHost = domDocument.createElement(DomManager.semanticsHostTagName);

    // Root element children.
    rootElement.appendChild(platformViewsHost);
    rootElement.appendChild(textEditingHost);

    // The semantic host goes last because hit-test order-wise it must be
    // first. If semantics goes under the scene host, platform views will
    // obscure semantic elements.
    //
    // You may be wondering: wouldn't semantics obscure platform views and
    // make then not accessible? At least with some careful planning, that
    // should not be the case. The semantics tree makes all of its non-leaf
    // elements transparent. This way, if a platform view appears among other
    // interactive Flutter widgets, as long as those widgets do not intersect
    // with the platform view, the platform view will be reachable.
    rootElement.appendChild(semanticsHost);

    // Rendering host (shadow root) children.

    renderingHost.append(sceneHost);

    // Styling.

    StyleManager.attachGlobalStyles(
      node: rootElement,
      styleId: 'flt-text-editing-stylesheet',
      styleNonce: configuration.nonce,
      cssSelectorPrefix: DomManager.flutterViewTagName,
    );

    StyleManager.attachGlobalStyles(
      node: renderingHost,
      styleId: 'flt-internals-stylesheet',
      styleNonce: configuration.nonce,
      cssSelectorPrefix: '',
    );

    StyleManager.styleSceneHost(
      sceneHost,
      debugShowSemanticsNodes: configuration.debugShowSemanticsNodes,
    );

    StyleManager.styleSemanticsHost(
      semanticsHost,
      devicePixelRatio,
    );

    return DomManager._(
      rootElement: rootElement,
      platformViewsHost: platformViewsHost,
      renderingHost: renderingHost,
      sceneHost: sceneHost,
      textEditingHost: textEditingHost,
      semanticsHost: semanticsHost,
    );
  }

  DomManager._({
    required this.rootElement,
    required this.platformViewsHost,
    required this.renderingHost,
    required this.sceneHost,
    required this.textEditingHost,
    required this.semanticsHost,
  });

  /// The tag name for the Flutter View root element.
  static const String flutterViewTagName = 'flutter-view';

  /// The tag name for the glass-pane.
  static const String glassPaneTagName = 'flt-glass-pane';

  /// The tag name for the scene host.
  static const String sceneHostTagName = 'flt-scene-host';

  /// The tag name for the text editing host.
  static const String textEditingHostTagName = 'flt-text-editing-host';

  /// The tag name for the semantics host.
  static const String semanticsHostTagName = 'flt-semantics-host';

  /// The root DOM element for the entire Flutter View.
  ///
  /// This is where input events are captured, such as pointer events.
  ///
  /// If semantics is enabled, this element also contains the semantics DOM tree,
  /// which captures semantics input events.
  final DomElement rootElement;

  /// Hosts all platform view elements.
  final DomElement platformViewsHost;

  /// Hosts all rendering elements and canvases.
  final DomShadowRoot renderingHost;

  /// Hosts the <flt-scene> element.
  ///
  /// This element is created and inserted in the HTML DOM once. It is never
  /// removed or moved. However the <flt-scene> inside of it may be replaced.
  final DomElement sceneHost;

  /// Hosts all text editing elements.
  final DomElement textEditingHost;

  /// Hosts the semantics tree.
  ///
  /// This element is in front of the [renderingHost] and [platformViewsHost].
  /// Otherwise, the phone will disable focusing by touch, only by tabbing
  /// around the UI.
  final DomElement semanticsHost;

  DomElement? _lastSceneElement;

  /// Inserts the [sceneElement] into the DOM and removes the existing scene (if
  /// any).
  ///
  /// The [sceneElement] is inserted  as a child of the <flt-scene-host> element
  /// inside the [renderingHost].
  ///
  /// If the [sceneElement] has already been inserted, this method does nothing
  /// to avoid unnecessary DOM mutations. This is both faster and more correct,
  /// because moving DOM nodes loses internal state, such as text selection.
  void setScene(DomElement sceneElement) {
    if (sceneElement != _lastSceneElement) {
      _lastSceneElement?.remove();
      _lastSceneElement = sceneElement;
      sceneHost.append(sceneElement);
    }
  }

  /// Injects a platform view with [platformViewId] into [platformViewsHost].
  ///
  /// If the platform view is already injected, this method does *nothing*.
  ///
  /// The `platformViewsHost` can only be different if `platformViewId` is moving
  /// from one [FlutterView] to another. In that case, the browser will move the
  /// slot contents from the old `platformViewsHost` to the new one, but that
  /// will cause the platformView to reset its state (an iframe will re-render,
  /// text selections will be lost, video playback interrupted, etc...)
  ///
  /// Try not to move platform views across views!
  void injectPlatformView(int platformViewId) {
    // For now, we don't need anything fancier. If needed, this can be converted
    // to a PlatformViewStrategy class for each web-renderer backend?
    final DomElement? pv = PlatformViewManager.instance.getSlottedContent(platformViewId);
    if (pv == null) {
      domWindow.console.debug('Failed to inject Platform View Id: $platformViewId. '
        'Render seems to be happening before a `flutter/platform_views:create` platform message!');
      return;
    }
    // If pv is already a descendant of platformViewsHost -> noop
    if (pv.parent == platformViewsHost) {
      return;
    }
    platformViewsHost.append(pv);
  }
}

DomShadowRoot _attachShadowRoot(DomElement element) {
  assert(
    getJsProperty<Object?>(element, 'attachShadow') != null,
    'ShadowDOM is not supported in this browser.',
  );

  return element.attachShadow(<String, dynamic>{
    'mode': 'open',
    // This needs to stay false to prevent issues like this:
    // - https://github.com/flutter/flutter/issues/85759
    'delegatesFocus': false,
  });
}
