// Copyright (c) 2024, 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:convert' hide json;
import 'dart:js_interop';

import 'package:path/path.dart' as p;

import 'js/filesystem_api.dart';

/// A class to read from the browser-compat-data files and parse interface and
/// property status (standards track, experimental, deprecated) and supported
/// browser (chrome, safari, firefox) info.
class BrowserCompatData {
  static final Map<String, Set<BCDPropertyStatus>> _eventHandlers = {};

  /// Returns whether [name] is an event handler that is supported in any
  /// interface.
  static bool isEventHandlerSupported(String name) =>
      _eventHandlers[name]?.any((bcd) => bcd.shouldGenerate) == true;

  static BrowserCompatData read({required bool generateAll}) {
    final path =
        p.join('node_modules', '@mdn', 'browser-compat-data', 'data.json');
    final content = (fs.readFileSync(
      path.toJS,
      JSReadFileOptions(encoding: 'utf8'.toJS),
    ) as JSString)
        .toDart;

    final contentMap = jsonDecode(content) as Map;
    final api = contentMap['api'] as Map<String, dynamic>;
    // MDN files WebAssembly compat data in a separate folder, so we need to
    // unify.
    final webassembly = (contentMap['webassembly']
        as Map<String, dynamic>)['api'] as Map<String, dynamic>;
    api.addAll(webassembly);
    // Add info for the namespace as well.
    api['WebAssembly'] = webassembly;

    final interfaces = <BCDInterfaceStatus>{};
    final globals = <String, Map<String, dynamic>>{};
    final globalInterfaces = <BCDInterfaceStatus>{};
    const globalsFilePrefix = 'api/_globals';

    for (final symbolName in api.symbolNames) {
      final apiInfo = api[symbolName] as Map<String, dynamic>;
      final interface = BCDInterfaceStatus(symbolName, apiInfo, generateAll);
      if (interface._sourceFile.startsWith(globalsFilePrefix)) {
        // MDN stores global members e.g. `isSecureContext` in the same location
        // as the interfaces. These are not interfaces, but rather properties
        // that should go in `Window` and `WorkerGlobalScope`. We cache the
        // compat data and add them directly to the relevant interfaces later.
        // https://github.com/mdn/browser-compat-data/blob/main/docs/data-guidelines/api.md#global-apis
        globals[symbolName] = apiInfo;
        // The compat data for the console namespace is within this property. It
        // should be exposed both as a global and as a namespace.
        if (symbolName == 'console') interfaces.add(interface);
      } else {
        interfaces.add(interface);
      }
      if (symbolName == 'Window' || symbolName == 'WorkerGlobalScope') {
        globalInterfaces.add(interface);
      }
    }

    globals.forEach((name, apiInfo) {
      for (final globalInterface in globalInterfaces) {
        globalInterface.addProperty(name, apiInfo, generateAll);
      }
    });

    return BrowserCompatData(
        Map.fromIterable(
          interfaces,
          key: (i) => (i as BCDInterfaceStatus).name,
        ),
        generateAll);
  }

  final Map<String, BCDInterfaceStatus> interfaces;

  /// Whether to generate all the bindings regardless of property status.
  bool generateAll = false;

  BrowserCompatData(this.interfaces, this.generateAll);

  BCDInterfaceStatus? retrieveInterfaceFor(String name) => interfaces[name];

  bool shouldGenerateInterface(String name) =>
      generateAll || (retrieveInterfaceFor(name)?.shouldGenerate ?? false);
}

class BCDInterfaceStatus extends BCDItem {
  final Map<String, BCDPropertyStatus> _properties = {};

  late final bool shouldGenerate;

  BCDInterfaceStatus(super.name, super.json, bool generateAll) {
    for (final symbolName in json.symbolNames) {
      addProperty(
          symbolName, json[symbolName] as Map<String, dynamic>, generateAll);
    }
    shouldGenerate = generateAll || (standardTrack && !experimental);
  }

  void addProperty(
      String property, Map<String, dynamic> compat, bool generateAll) {
    // Event compatibility data is stored as `<name_of_event>_event`. In order
    // to have compatibility data for `onX` properties, we need to replace such
    // property names. See https://github.com/mdn/browser-compat-data/blob/main/docs/data-guidelines/api.md#dom-events-eventname_event
    // for more details.
    late BCDPropertyStatus status;
    const eventSuffix = '_event';
    if (property.endsWith(eventSuffix)) {
      property = 'on${property.replaceAll(eventSuffix, '')}';
      status = BCDPropertyStatus(property, compat, this, generateAll);
      BrowserCompatData._eventHandlers
          .putIfAbsent(property, () => {})
          .add(status);
    } else {
      status = BCDPropertyStatus(property, compat, this, generateAll);
    }
    _properties[property] = status;
  }

  BCDPropertyStatus? retrievePropertyFor(String name, {bool isStatic = false}) {
    if (isStatic) name = '${name}_static';
    return _properties[name];
  }
}

class BCDPropertyStatus extends BCDItem {
  final BCDInterfaceStatus parent;

  late final bool shouldGenerate;

  BCDPropertyStatus(super.name, super.json, this.parent, bool generateAll) {
    shouldGenerate = generateAll || (standardTrack && !experimental);
  }
}

abstract class BCDItem {
  final String name;
  final Map<String, dynamic> json;

  BCDItem(this.name, this.json);

  Map<String, dynamic> get _compat => json['__compat'] as Map<String, dynamic>;
  String get _sourceFile => _compat['source_file'] as String;
  Map<String, dynamic> get _status => _compat['status'] as Map<String, dynamic>;
  Map<String, dynamic> get _support =>
      _compat['support'] as Map<String, dynamic>;

  bool get deprecated => _status['deprecated'] as bool? ?? false;
  bool get experimental => _status['experimental'] as bool? ?? false;
  bool get standardTrack => _status['standard_track'] as bool? ?? false;

  List<String> get status => [
        if (standardTrack) 'standards-track',
        if (deprecated) 'deprecated',
        if (experimental) 'experimental',
      ];

  String get _statusDescription => status.join(', ');

  bool get chromeSupported => _supportedInBrowser('chrome');
  bool get firefoxSupported => _supportedInBrowser('firefox');
  bool get safariSupported => _supportedInBrowser('safari');

  List<String> get browsers => [
        if (chromeSupported) 'chrome',
        if (firefoxSupported) 'firefox',
        if (safariSupported) 'safari',
      ];

  String get _browsersDescription => browsers.join(', ');

  bool _supportedInBrowser(String browser) {
    final map = (_support[browser] is List
        ? (_support[browser] as List).first
        : _support[browser]) as Map<String, dynamic>;

    if (map.containsKey('version_removed')) {
      return false;
    }

    final value = map['version_added'];
    if (value is String) return true;
    if (value is bool) return value;
    return false;
  }

  @override
  String toString() => '$name ($_browsersDescription) [$_statusDescription]';
}

extension BCDJsonDataExtension on Map<String, dynamic> {
  /// Return keys which correspond to symbol names (i.e., filter out non-symbol
  /// metadata (`__meta`, `__compat`, ...).
  Iterable<String> get symbolNames => keys.where((key) => !key.startsWith('_'));
}
