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

import 'dart:js_util' as js_util;

import 'package:js/js.dart';

@JS()
@staticInterop
class Window extends EventTarget {}

extension WindowExtension on Window {
  @pragma('dart2js:as:trust')
  Window get parent => js_util.getProperty<dynamic>(this, 'parent') as Window;
  external Location get location;
  Console get console => js_util.getProperty(this, 'console') as Console;
  CSSStyleDeclaration? getComputedStyle(Element elt, [String? pseudoElt]) =>
      js_util.callMethod(this, 'getComputedStyle', <Object>[
        elt,
        if (pseudoElt != null) pseudoElt
      ]) as CSSStyleDeclaration?;
  external Navigator get navigator;
  void postMessage(Object message, String targetOrigin,
          [List<MessagePort>? messagePorts]) =>
      js_util.callMethod(this, 'postMessage', <Object?>[
        js_util.jsify(message),
        targetOrigin,
        if (messagePorts != null) js_util.jsify(messagePorts)
      ]);
}

@JS('window')
external Window get window;

@JS()
@staticInterop
class Console {}

extension ConsoleExtension on Console {
  external void log(Object? object);
  external void warn(Object? object);
}

@JS()
@staticInterop
class Document extends Node {}

extension DocumentExtension on Document {
  external Element? querySelector(String selectors);
  Element createElement(String name, [Object? options]) => js_util.callMethod(
          this, 'createElement', <Object>[name, if (options != null) options])
      as Element;
}

@JS()
@staticInterop
class HTMLDocument extends Document {}

extension HTMLDocumentExtension on HTMLDocument {
  external HTMLBodyElement? get body;
  external String? get title;
}

@JS('document')
external HTMLDocument get document;

@JS()
@staticInterop
class Navigator {}

extension NavigatorExtension on Navigator {
  external String get userAgent;
}

@JS()
@staticInterop
class Element extends Node {}

extension DomElementExtension on Element {
  external DomTokenList get classList;
}

@JS()
@staticInterop
class HTMLElement extends Element {}

@JS()
@staticInterop
class HTMLBodyElement extends HTMLElement {}

@JS()
@staticInterop
class Node extends EventTarget {}

extension NodeExtension on Node {
  external Node appendChild(Node node);
  void remove() {
    if (parentNode != null) {
      final parent = parentNode!;
      parent.removeChild(this);
    }
  }

  external Node removeChild(Node child);
  external Node? get parentNode;
}

@JS()
@staticInterop
class EventTarget {}

extension EventTargetExtension on EventTarget {
  void addEventListener(String type, EventListener? listener,
      [bool? useCapture]) {
    if (listener != null) {
      js_util.callMethod<void>(this, 'addEventListener',
          <Object>[type, listener, if (useCapture != null) useCapture]);
    }
  }

  void removeEventListener(String type, EventListener? listener,
      [bool? useCapture]) {
    if (listener != null) {
      js_util.callMethod<void>(this, 'removeEventListener',
          <Object>[type, listener, if (useCapture != null) useCapture]);
    }
  }
}

typedef EventListener = void Function(Event event);

@JS()
@staticInterop
class Event {}

extension EventExtension on Event {
  external void stopPropagation();
}

@JS()
@staticInterop
class MessageEvent extends Event {}

extension MessageEventExtension on MessageEvent {
  dynamic get data => js_util.dartify(js_util.getProperty(this, 'data'));
  external String get origin;
  List<MessagePort> get ports =>
      js_util.getProperty<List>(this, 'ports').cast<MessagePort>();

  /// The source may be a `WindowProxy`, a `MessagePort`, or a `ServiceWorker`.
  ///
  /// When a message is sent from an iframe through `window.parent.postMessage`
  /// the source will be a `WindowProxy` which has the same methods as [Window].
  @pragma('dart2js:as:trust')
  MessageEventSource get source =>
      js_util.getProperty<dynamic>(this, 'source') as MessageEventSource;
}

@JS()
@staticInterop
class MessageEventSource {}

extension MessageEventSourceExtension on MessageEventSource {
  @pragma('dart2js:as:trust')
  MessageEventSourceLocation? get location =>
      js_util.getProperty<dynamic>(this, 'location')
          as MessageEventSourceLocation;
}

@JS()
@staticInterop
class MessageEventSourceLocation {}

extension MessageEventSourceLocationExtension on MessageEventSourceLocation {
  external String? get href;
}

@JS()
@staticInterop
class Location {}

extension LocationExtension on Location {
  external String get href;
  external String get origin;
}

@JS()
@staticInterop
class MessagePort extends EventTarget {}

extension MessagePortExtension on MessagePort {
  void postMessage(Object? message) => js_util.callMethod(this, 'postMessage',
      <Object>[if (message != null) js_util.jsify(message) as Object]);
  external void start();
}

@JS()
@staticInterop
class CSSStyleDeclaration {}

@JS()
@staticInterop
class HTMLScriptElement extends HTMLElement {}

extension HTMLScriptElementExtension on HTMLScriptElement {
  external set src(String value);
}

HTMLScriptElement createHTMLScriptElement() =>
    document.createElement('script') as HTMLScriptElement;

@JS()
@staticInterop
class DomTokenList {}

extension DomTokenListExtension on DomTokenList {
  external void add(String value);
  external void remove(String value);
  external bool contains(String token);
}

@JS()
@staticInterop
class HTMLIFrameElement extends HTMLElement {}

extension HTMLIFrameElementExtension on HTMLIFrameElement {
  external String? get src;
  external set src(String? value);
  external Window get contentWindow;
}

HTMLIFrameElement createHTMLIFrameElement() =>
    document.createElement('iframe') as HTMLIFrameElement;

@JS()
@staticInterop
class WebSocket extends EventTarget {}

extension WebSocketExtension on WebSocket {
  external void send(Object? data);
}

WebSocket createWebSocket(String url) =>
    _callConstructor('WebSocket', <Object>[url])! as WebSocket;

@JS()
@staticInterop
class MessageChannel {}

extension MessageChannelExtension on MessageChannel {
  external MessagePort get port1;
  external MessagePort get port2;
}

MessageChannel createMessageChannel() =>
    _callConstructor('MessageChannel', <Object>[])! as MessageChannel;

Object? _findConstructor(String constructorName) =>
    js_util.getProperty(window, constructorName);

Object? _callConstructor(String constructorName, List<Object?> args) {
  final constructor = _findConstructor(constructorName);
  if (constructor == null) {
    return null;
  }
  return js_util.callConstructor(constructor, args);
}

class Subscription {
  final String type;
  final EventTarget target;
  final EventListener listener;

  Subscription(this.target, this.type, this.listener) {
    target.addEventListener(type, listener);
  }

  void cancel() => target.removeEventListener(type, listener);
}
