// Copyright (c) 2020, 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';

import 'package:async/async.dart';
import 'package:dwds/src/debugging/metadata/module_metadata.dart';
import 'package:dwds/src/readers/asset_reader.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as p;

/// A provider of metadata in which data is collected through DDC outputs.
class MetadataProvider {
  final AssetReader _assetReader;
  final _logger = Logger('MetadataProvider');
  final String entrypoint;
  final Set<String> _libraries = {};
  final Map<String, String> _scriptToModule = {};
  final Map<String, String> _moduleToSourceMap = {};
  final Map<String, String> _modulePathToModule = {};
  final Map<String, String> _moduleToModulePath = {};
  final Map<String, Set<String>> _moduleToLibraries = {};
  final Map<String, List<String>> _scripts = {};
  final _metadataMemoizer = AsyncMemoizer();

  /// Implicitly imported libraries in any DDC component.
  ///
  /// Currently dart_sdk module does not come with the metadata.
  /// To allow evaluation of expressions that use libraries and
  /// types from the SDK (such as a dart Type object), add the
  /// metadata for dart_sdk manually.
  ///
  /// TODO: Generate sdk module metadata to be consumed by debugger.
  /// Issue: https://github.com/dart-lang/sdk/issues/45477
  List<String> get sdkLibraries => const [
    'dart:_runtime',
    'dart:_debugger',
    'dart:_foreign_helper',
    'dart:_interceptors',
    'dart:_internal',
    'dart:_isolate_helper',
    'dart:_js_helper',
    'dart:_js_primitives',
    'dart:_metadata',
    'dart:_native_typed_data',
    'dart:_rti',
    'dart:async',
    'dart:collection',
    'dart:convert',
    'dart:core',
    'dart:developer',
    'dart:io',
    'dart:isolate',
    'dart:js',
    'dart:js_util',
    'dart:math',
    'dart:typed_data',
    'dart:indexed_db',
    'dart:html',
    'dart:html_common',
    'dart:svg',
    'dart:web_audio',
    'dart:web_gl',
    'dart:ui',
  ];

  MetadataProvider(this.entrypoint, this._assetReader);

  /// A list of all libraries in the Dart application.
  ///
  /// Example:
  ///
  ///  [
  ///     dart:web_gl,
  ///     dart:math,
  ///     org-dartlang-app:///web/main.dart
  ///  ]
  ///
  Future<List<String>> get libraries async {
    await _initialize();
    return _libraries.toList();
  }

  /// A map of library uri to dart scripts.
  ///
  /// Example:
  ///
  /// {
  ///   org-dartlang-app:///web/main.dart :
  ///   { web/main.dart  }
  /// }
  ///
  Future<Map<String, List<String>>> get scripts async {
    await _initialize();
    return _scripts;
  }

  /// A map of script to containing module.
  ///
  /// Example:
  ///
  /// {
  ///   org-dartlang-app:///web/main.dart :
  ///   web/main
  /// }
  Future<Map<String, String>> get scriptToModule async {
    await _initialize();
    return _scriptToModule;
  }

  /// A map of module name to source map path.
  ///
  /// Example:
  ///
  /// {
  ///   org-dartlang-app:///web/main.dart :
  ///   web/main.ddc.js.map
  /// }
  Future<Map<String, String>> get moduleToSourceMap async {
    await _initialize();
    return _moduleToSourceMap;
  }

  /// A map of module path to module name.
  ///
  /// Example:
  ///
  /// {
  ///   web/main.ddc.js :
  ///   web/main
  /// }
  Future<Map<String, String>> get modulePathToModule async {
    await _initialize();
    return _modulePathToModule;
  }

  /// A map of module to module path.
  ///
  /// Example:
  ///
  /// {
  ///   web/main
  ///   web/main.ddc.js :
  /// }
  Future<Map<String, String>> get moduleToModulePath async {
    await _initialize();
    return _moduleToModulePath;
  }

  /// A list of module ids.
  ///
  /// Example:
  ///
  /// [
  ///   web/main,
  ///   web/foo/bar
  /// ]
  Future<List<String>> get modules async {
    await _initialize();
    return _moduleToModulePath.keys.toList();
  }

  /// Compute metadata information after reading the metadata contents and
  /// return a map from module names to their [ModuleMetadata].
  Future<Map<String, ModuleMetadata>> _processMetadata() async {
    final modules = <String, ModuleMetadata>{};
    // The merged metadata resides next to the entrypoint.
    // Assume that <name>.bootstrap.js has <name>.ddc_merged_metadata
    if (entrypoint.endsWith('.bootstrap.js')) {
      _logger.info('Loading debug metadata...');
      final serverPath = entrypoint.replaceAll(
        '.bootstrap.js',
        '.ddc_merged_metadata',
      );
      final merged = await _assetReader.metadataContents(serverPath);
      if (merged != null) {
        for (final contents in merged.split('\n')) {
          try {
            if (contents.isEmpty ||
                contents.startsWith('// intentionally empty:')) {
              continue;
            }
            final moduleJson = json.decode(contents);
            final metadata = ModuleMetadata.fromJson(
              moduleJson as Map<String, dynamic>,
            );
            final moduleName = metadata.name;
            modules[moduleName] = metadata;
            _logger.fine('Loaded debug metadata for module: $moduleName');
          } catch (e) {
            _logger.warning('Failed to read metadata: $e');
            rethrow;
          }
        }
      }
    }
    return modules;
  }

  /// Process all metadata, including SDK metadata, and compute caches once.
  Future<void> _initialize() async {
    await _metadataMemoizer.runOnce(() async {
      final metadata = await _processMetadata();
      _addSdkMetadata();
      metadata.values.forEach(_addMetadata);
    });
  }

  /// Given a map of hot reloaded modules mapped to their respective libraries,
  /// determines deleted and invalidated libraries and modules, invalidates them
  /// in any caches, and recomputes the necessary information.
  ///
  /// Returns a [ModifiedModuleReport] that can be used to invalidate other
  /// caches after a hot reload.
  Future<ModifiedModuleReport> reinitializeAfterHotReload(
    Map<String, List> reloadedModulesToLibraries,
  ) async {
    final modules = await _processMetadata();
    final invalidatedLibraries = <String>{};
    void invalidateLibrary(String libraryImportUri) {
      invalidatedLibraries.add(libraryImportUri);
      _libraries.remove(libraryImportUri);
      _scriptToModule.remove(libraryImportUri);
      _scripts[libraryImportUri]?.forEach(_scriptToModule.remove);
      _scripts.remove(libraryImportUri);
    }

    final deletedModules = <String>{};
    for (final module in _moduleToLibraries.keys) {
      final deletedModule = !modules.containsKey(module);
      final invalidatedModule = reloadedModulesToLibraries.containsKey(module);
      assert(!(deletedModule && invalidatedModule));
      // If the module was either deleted or reloaded, invalidate all previous
      // information both about the module and its libraries.
      if (deletedModule || invalidatedModule) {
        _modulePathToModule.remove(module);
        _moduleToLibraries[module]?.forEach(invalidateLibrary);
        _moduleToModulePath.remove(module);
        _moduleToSourceMap.remove(module);
      }
      if (deletedModule) deletedModules.add(module);
    }
    final reloadedModules = <String>{};
    final reloadedLibraries = <String>{};
    for (final module in reloadedModulesToLibraries.keys) {
      reloadedModules.add(module);
      reloadedLibraries.addAll(
        reloadedModulesToLibraries[module]!.cast<String>(),
      );
      _addMetadata(modules[module]!);
    }
    // The libraries that are removed from the program are those that we
    // invalidated but were never added again.
    final deletedLibraries = invalidatedLibraries
        .where((library) => !_libraries.contains(library))
        .toSet();
    return ModifiedModuleReport(
      deletedModules: deletedModules,
      deletedLibraries: deletedLibraries,
      reloadedModules: reloadedModules,
      reloadedLibraries: reloadedLibraries,
    );
  }

  void _addMetadata(ModuleMetadata metadata) {
    final modulePath = stripLeadingSlashes(metadata.moduleUri);
    final sourceMapPath = stripLeadingSlashes(metadata.sourceMapUri);
    final moduleName = metadata.name;

    _moduleToSourceMap[moduleName] = sourceMapPath;
    _modulePathToModule[modulePath] = moduleName;
    _moduleToModulePath[moduleName] = modulePath;

    final moduleLibraries = <String>{};
    for (final library in metadata.libraries.values) {
      if (library.importUri.startsWith('file:/')) {
        throw AbsoluteImportUriException(library.importUri);
      }
      moduleLibraries.add(library.importUri);
      _libraries.add(library.importUri);
      _scripts[library.importUri] = [];

      _scriptToModule[library.importUri] = moduleName;
      for (final path in library.partUris) {
        // Parts in metadata are relative to the library Uri directory.
        final partPath = p.url.join(p.dirname(library.importUri), path);
        _scripts[library.importUri]!.add(partPath);
        _scriptToModule[partPath] = moduleName;
      }
    }
    _moduleToLibraries[moduleName] = moduleLibraries;
  }

  void _addSdkMetadata() {
    final moduleName = 'dart_sdk';

    for (final lib in sdkLibraries) {
      _libraries.add(lib);
      _scripts[lib] = [];
      // TODO(srujzs): It feels weird that we add this mapping to only this map
      // and not any of the other module maps. We should maybe handle this
      // differently. This will become relevant if we ever support hot reload
      // for the Dart SDK.
      _scriptToModule[lib] = moduleName;
    }
  }
}

class AbsoluteImportUriException implements Exception {
  final String importUri;
  AbsoluteImportUriException(this.importUri);

  @override
  String toString() => "AbsoluteImportUriError: '$importUri'";
}

/// Computed after a hot reload using
/// [MetadataProvider.reinitializeAfterHotReload], represents the modules and
/// libraries in the program that were deleted, reloaded, and therefore,
/// modified.
///
/// Used to recompute caches throughout DWDS.
class ModifiedModuleReport {
  /// Module names that are no longer in the program.
  final Set<String> deletedModules;

  /// Library uris that are no longer in the program.
  final Set<String> deletedLibraries;

  /// Module names that were loaded during the hot reload.
  final Set<String> reloadedModules;

  /// Library uris that were loaded during the hot reload.
  final Set<String> reloadedLibraries;

  /// Module names that were either removed or modified, including additions.
  final Set<String> modifiedModules;

  /// Library uris that were either removed or modified, including additions.
  final Set<String> modifiedLibraries;
  ModifiedModuleReport({
    required this.deletedModules,
    required this.deletedLibraries,
    required this.reloadedModules,
    required this.reloadedLibraries,
  }) : modifiedModules = deletedModules.union(reloadedModules),
       modifiedLibraries = deletedLibraries.union(reloadedLibraries);
}
