// Copyright (c) 2019, 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 'dart:io';

import 'package:dev_compiler/dev_compiler.dart' show Compiler;
import 'package:frontend_server/src/javascript_bundle.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
import 'package:package_config/package_config.dart';
import 'package:test/test.dart';

/// Additional indexed types required by the dev_compiler's NativeTypeSet.
final Map<String, Map<String, List<String>>> additionalRequiredClasses = {
  'dart:core': {'Comparable': []},
  'dart:async': {
    'StreamIterator': ['get:current', 'moveNext', 'cancel', ''],
    '_SyncStarIterator': ['_current', '_datum', '_yieldStar'],
    '_IterationMarker': ['yieldSingle', 'yieldStar'],
  },
  'dart:_interceptors': {
    'JSBool': [],
    'JSNumber': [],
    'JSArray': [],
    'JSString': [],
    'LegacyJavaScriptObject': [],
  },
  'dart:_native_typed_data': {},
  'dart:collection': {
    'ListBase': [],
    'MapBase': [],
    'LinkedHashSet': [],
    '_HashSet': [],
    '_IdentityHashSet': [],
  },
  'dart:math': {'Rectangle': []},
  'dart:html': {},
  'dart:_rti': {'Rti': [], '_Universe': []},
  'dart:indexed_db': {},
  'dart:svg': {},
  'dart:web_audio': {},
  'dart:web_gl': {},
  'dart:_js_helper': {
    'PrivateSymbol': [],
    'LinkedMap': [],
    'IdentityMap': [],
    'LinkedSet': [],
    'IdentitySet': [],
    'SyncIterable': [],
  },
};

/// Additional indexed top level methods required by the dev_compiler.
final Map<String, List<String>> requiredTopLevels = {
  'dart:_runtime': ['assertInterop'],
  'dart:async': [
    '_asyncAwait',
    '_asyncReturn',
    '_asyncRethrow',
    '_asyncStarHelper',
    '_asyncStartSync',
    '_makeAsyncAwaitCompleter',
    '_makeSyncStarIterable',
    '_makeAsyncStarStreamController',
    '_makeSyncStarIterable',
    '_streamOfController',
    '_wrapJsFunctionForAsync',
  ],
  'dart:_rti': [
    '_asBool',
    '_asDouble',
    '_asInt',
    '_asNum',
    '_asObject',
    '_asString',
    '_asBoolQ',
    '_asDoubleQ',
    '_asIntQ',
    '_asNumQ',
    '_asStringQ',
  ],
};

void main() {
  Map<String, List<String>> allRequiredTypes = _combineMaps(
    CoreTypes.requiredClasses,
    additionalRequiredClasses.map((k, v) => new MapEntry(k, v.keys.toList())),
  );
  List<String> allRequiredLibraries = [
    ...allRequiredTypes.keys,
    ...requiredTopLevels.keys,
  ];
  List<Library> testCoreLibraries = [];
  for (String requiredLibrary in allRequiredLibraries) {
    Library library = new Library(
      Uri.parse(requiredLibrary),
      fileUri: Uri.parse(requiredLibrary),
    );
    for (String requiredClass in allRequiredTypes[requiredLibrary] ?? []) {
      List<String> requiredMembers =
          (additionalRequiredClasses[requiredLibrary]?[requiredClass] ?? []);
      library.addClass(
        new Class(
          name: requiredClass,
          fileUri: Uri.parse(requiredLibrary),
          procedures: [
            for (String requiredMember in requiredMembers)
              new Procedure(
                new Name(requiredMember, library),
                ProcedureKind.Method,
                new FunctionNode(new EmptyStatement()),
                fileUri: Uri.parse(requiredLibrary),
              ),
          ],
        ),
      );
    }
    for (String requiredMember in requiredTopLevels[requiredLibrary] ?? []) {
      library.addProcedure(
        new Procedure(
          new Name(requiredMember, library),
          ProcedureKind.Method,
          new FunctionNode(new EmptyStatement()),
          fileUri: Uri.parse(requiredLibrary),
        ),
      );
    }
    testCoreLibraries.add(library);
  }

  final PackageConfig packageConfig = PackageConfig.parseJson({
    'configVersion': 2,
    'packages': [
      {'name': 'a', 'rootUri': 'file:///pkg/a', 'packageUri': 'lib/'},
    ],
  }, Uri.base);
  final String multiRootScheme = 'org-dartlang-app';

  for (final bool debuggerNames in [true, false]) {
    group('Debugger module names: $debuggerNames |', () {
      test('Creates component uris for file paths', () async {
        final Uri fileUri = new Uri.file('/c.dart');

        final IncrementalJavaScriptBundler javaScriptBundler =
            new IncrementalJavaScriptBundler(
              null,
              {},
              multiRootScheme,
              useDebuggerModuleNames: debuggerNames,
            );

        final String componentUrl = javaScriptBundler.urlForComponentUri(
          fileUri,
          packageConfig,
        );
        final String libraryBundleName = javaScriptBundler
            .makeLibraryBundleName(componentUrl);
        expect(componentUrl, '/c.dart');
        expect(libraryBundleName, 'c.dart');
      });

      test('Creates component uris for package paths', () async {
        final Uri packageUri = Uri.parse('package:a/a.dart');

        final IncrementalJavaScriptBundler javaScriptBundler =
            new IncrementalJavaScriptBundler(
              null,
              {},
              multiRootScheme,
              useDebuggerModuleNames: debuggerNames,
            );

        final String componentUrl = javaScriptBundler.urlForComponentUri(
          packageUri,
          packageConfig,
        );
        final String libraryBundleName = javaScriptBundler
            .makeLibraryBundleName(componentUrl);
        expect(
          componentUrl,
          debuggerNames ? 'packages/a/lib/a.dart' : '/packages/a/a.dart',
        );
        expect(
          libraryBundleName,
          debuggerNames ? 'packages/a/lib/a.dart' : 'packages/a/a.dart',
        );
      });

      test('compiles JavaScript code', () async {
        final Uri uri = new Uri.file('/c.dart');
        final Library library = new Library(
          uri,
          fileUri: uri,
          procedures: [
            new Procedure(
              new Name('ArbitrarilyChosen'),
              ProcedureKind.Method,
              new FunctionNode(new Block([])),
              fileUri: uri,
            ),
          ],
        );
        final Component testComponent = new Component(
          libraries: [library, ...testCoreLibraries],
        );
        final IncrementalJavaScriptBundler javaScriptBundler =
            new IncrementalJavaScriptBundler(
              null,
              {},
              multiRootScheme,
              useDebuggerModuleNames: debuggerNames,
            );

        await javaScriptBundler.initialize(testComponent, uri, packageConfig);

        final _MemorySink manifestSink = new _MemorySink();
        final _MemorySink codeSink = new _MemorySink();
        final _MemorySink sourcemapSink = new _MemorySink();
        final _MemorySink metadataSink = new _MemorySink();
        final _MemorySink symbolsSink = new _MemorySink();
        final CoreTypes coreTypes = new CoreTypes(testComponent);

        final Map<String, Compiler> compilers = await javaScriptBundler.compile(
          new ClassHierarchy(testComponent, coreTypes),
          coreTypes,
          packageConfig,
          codeSink,
          manifestSink,
          sourcemapSink,
          metadataSink,
          symbolsSink,
        );

        final Map<String, dynamic> manifest = json.decode(
          utf8.decode(manifestSink.buffer),
        );
        final String code = utf8.decode(codeSink.buffer);

        expect(manifest, {
          '/c.dart.lib.js': {
            'code': [0, codeSink.buffer.length],
            'sourcemap': [0, sourcemapSink.buffer.length],
          },
        });
        expect(code, contains('ArbitrarilyChosen'));

        // Verify source map url is correct.
        expect(code, contains('sourceMappingURL=c.dart.lib.js.map'));

        // Verify program compilers are created.
        expect(compilers.keys, equals([library.importUri.toString()]));
      });

      test('converts package: uris into /packages/ uris', () async {
        Uri importUri = Uri.parse('package:a/a.dart');
        Uri fileUri = packageConfig.resolve(importUri)!;
        final Library library = new Library(
          importUri,
          fileUri: fileUri,
          procedures: [
            new Procedure(
              new Name('ArbitrarilyChosen'),
              ProcedureKind.Method,
              new FunctionNode(new Block([])),
              fileUri: fileUri,
            ),
          ],
        );

        final Component testComponent = new Component(
          libraries: [library, ...testCoreLibraries],
        );

        final IncrementalJavaScriptBundler javaScriptBundler =
            new IncrementalJavaScriptBundler(
              null,
              {},
              multiRootScheme,
              useDebuggerModuleNames: debuggerNames,
            );

        await javaScriptBundler.initialize(
          testComponent,
          importUri,
          packageConfig,
        );

        final _MemorySink manifestSink = new _MemorySink();
        final _MemorySink codeSink = new _MemorySink();
        final _MemorySink sourcemapSink = new _MemorySink();
        final _MemorySink metadataSink = new _MemorySink();
        final _MemorySink symbolsSink = new _MemorySink();
        final CoreTypes coreTypes = new CoreTypes(testComponent);

        await javaScriptBundler.compile(
          new ClassHierarchy(testComponent, coreTypes),
          coreTypes,
          packageConfig,
          codeSink,
          manifestSink,
          sourcemapSink,
          metadataSink,
          symbolsSink,
        );

        final Map<String, dynamic> manifest = json.decode(
          utf8.decode(manifestSink.buffer),
        );
        final String code = utf8.decode(codeSink.buffer);

        final String componentUrl = javaScriptBundler.urlForComponentUri(
          library.importUri,
          packageConfig,
        );

        expect(manifest, {
          '$componentUrl.lib.js': {
            'code': [0, codeSink.buffer.length],
            'sourcemap': [0, sourcemapSink.buffer.length],
          },
        });
        expect(code, contains('ArbitrarilyChosen'));

        // Verify source map url is correct.
        expect(code, contains('sourceMappingURL=a.dart.lib.js.map'));
      });

      test(
        'multi-root uris create library bundles relative to the root',
        () async {
          Uri importUri = Uri.parse('$multiRootScheme:/web/main.dart');
          Uri fileUri = importUri;
          final Library library = new Library(
            importUri,
            fileUri: fileUri,
            procedures: [
              new Procedure(
                new Name('ArbitrarilyChosen'),
                ProcedureKind.Method,
                new FunctionNode(new Block([])),
                fileUri: fileUri,
              ),
            ],
          );

          final Component testComponent = new Component(
            libraries: [library, ...testCoreLibraries],
          );

          final IncrementalJavaScriptBundler javaScriptBundler =
              new IncrementalJavaScriptBundler(
                null,
                {},
                multiRootScheme,
                useDebuggerModuleNames: debuggerNames,
              );

          await javaScriptBundler.initialize(
            testComponent,
            importUri,
            packageConfig,
          );

          final _MemorySink manifestSink = new _MemorySink();
          final _MemorySink codeSink = new _MemorySink();
          final _MemorySink sourcemapSink = new _MemorySink();
          final _MemorySink metadataSink = new _MemorySink();
          final _MemorySink symbolsSink = new _MemorySink();
          final CoreTypes coreTypes = new CoreTypes(testComponent);

          await javaScriptBundler.compile(
            new ClassHierarchy(testComponent, coreTypes),
            coreTypes,
            packageConfig,
            codeSink,
            manifestSink,
            sourcemapSink,
            metadataSink,
            symbolsSink,
          );

          final Map manifest = json.decode(utf8.decode(manifestSink.buffer));
          final String code = utf8.decode(codeSink.buffer);

          expect(manifest, {
            '${importUri.path}.lib.js': {
              'code': [0, codeSink.buffer.length],
              'sourcemap': [0, sourcemapSink.buffer.length],
            },
          });
          expect(code, contains('ArbitrarilyChosen'));

          // Verify source map url is correct.
          expect(code, contains('sourceMappingURL=main.dart.lib.js.map'));
        },
      );
    });
  }

  test('can combine strongly connected components', () async {
    // Create three libraries A, B, C where A is the entrypoint and B & C
    // circularly import each other.
    final Library libraryC = new Library(
      new Uri.file('/c.dart'),
      fileUri: new Uri.file('/c.dart'),
    );
    final Library libraryB = new Library(
      new Uri.file('/b.dart'),
      fileUri: new Uri.file('/b.dart'),
    );
    libraryC.dependencies.add(new LibraryDependency.import(libraryB));
    libraryB.dependencies.add(new LibraryDependency.import(libraryC));
    final Uri uriA = new Uri.file('/a.dart');
    final Library libraryA = new Library(
      uriA,
      fileUri: uriA,
      dependencies: [new LibraryDependency.import(libraryB)],
      procedures: [
        new Procedure(
          new Name('ArbitrarilyChosen'),
          ProcedureKind.Method,
          new FunctionNode(new Block([])),
          fileUri: uriA,
        ),
      ],
    );
    final Component testComponent = new Component(
      libraries: [libraryA, libraryB, libraryC, ...testCoreLibraries],
    );

    final IncrementalJavaScriptBundler javaScriptBundler =
        new IncrementalJavaScriptBundler(null, {}, multiRootScheme);

    await javaScriptBundler.initialize(testComponent, uriA, packageConfig);

    final _MemorySink manifestSink = new _MemorySink();
    final _MemorySink codeSink = new _MemorySink();
    final _MemorySink sourcemapSink = new _MemorySink();
    final _MemorySink metadataSink = new _MemorySink();
    final _MemorySink symbolsSink = new _MemorySink();
    final CoreTypes coreTypes = new CoreTypes(testComponent);

    await javaScriptBundler.compile(
      new ClassHierarchy(testComponent, coreTypes),
      coreTypes,
      packageConfig,
      codeSink,
      manifestSink,
      sourcemapSink,
      metadataSink,
      symbolsSink,
    );

    final String code = utf8.decode(codeSink.buffer);
    final Map<String, dynamic> manifest = json.decode(
      utf8.decode(manifestSink.buffer),
    );

    // There should only be two modules since C and B should be combined.
    final String moduleHeader = r"define(['dart_sdk'], (function load__";
    expect(moduleHeader.allMatches(code), hasLength(2));

    // Expected module headers.
    final String aModuleHeader =
        r"define(['dart_sdk'], (function load__a_dart(dart_sdk) {";
    expect(code, contains(aModuleHeader));
    final String cModuleHeader =
        r"define(['dart_sdk'], (function load__c_dart(dart_sdk) {";
    expect(code, contains(cModuleHeader));

    // Verify source map url is correct.
    expect(code, contains('sourceMappingURL=a.dart.lib.js.map'));

    final List<dynamic> offsets = manifest['/a.dart.lib.js']['sourcemap'];
    final Map<String, dynamic> sourcemapModuleA = json.decode(
      utf8.decode(sourcemapSink.buffer.sublist(offsets.first, offsets.last)),
    );

    // Verify source maps are pointing at correct source files.
    expect(sourcemapModuleA['file'], 'a.dart.lib.js');
  });

  test('can invalidate changes to strongly connected components', () async {
    final Uri uriA = new Uri.file('/a.dart');
    final Uri uriB = new Uri.file('/b.dart');
    final Uri uriC = new Uri.file('/c.dart');

    // Create three libraries A, B, C where A is the entrypoint and B & C
    // circularly import each other.
    final Library libraryC = new Library(uriC, fileUri: uriC);
    final Library libraryB = new Library(uriB, fileUri: uriB);
    libraryC.dependencies.add(new LibraryDependency.import(libraryB));
    libraryB.dependencies.add(new LibraryDependency.import(libraryC));
    final Library libraryA = new Library(
      uriA,
      fileUri: uriA,
      dependencies: [new LibraryDependency.import(libraryB)],
      procedures: [
        new Procedure(
          new Name('ArbitrarilyChosen'),
          ProcedureKind.Method,
          new FunctionNode(new Block([])),
          fileUri: uriA,
        ),
      ],
    );
    final Component testComponent = new Component(
      libraries: [libraryA, libraryB, libraryC, ...testCoreLibraries],
    );

    final IncrementalJavaScriptBundler javaScriptBundler =
        new IncrementalJavaScriptBundler(null, {}, multiRootScheme);

    await javaScriptBundler.initialize(testComponent, uriA, packageConfig);

    // Now change A and B so that they no longer import each other.
    final Library libraryC2 = new Library(uriC, fileUri: uriC);
    final Library libraryB2 = new Library(uriB, fileUri: uriB);
    libraryB2.dependencies.add(new LibraryDependency.import(libraryC2));
    final Library libraryA2 = new Library(
      uriA,
      fileUri: uriA,
      dependencies: [new LibraryDependency.import(libraryB2)],
      procedures: [
        new Procedure(
          new Name('ArbitrarilyChosen'),
          ProcedureKind.Method,
          new FunctionNode(new Block([])),
          fileUri: uriA,
        ),
      ],
    );
    final Component partialComponent = new Component(
      libraries: [libraryA2, libraryB2, libraryC2],
    );

    await javaScriptBundler.invalidate(
      partialComponent,
      testComponent,
      uriA,
      packageConfig,
      recompileRestart: false,
    );

    final _MemorySink manifestSink = new _MemorySink();
    final _MemorySink codeSink = new _MemorySink();
    final _MemorySink sourcemapSink = new _MemorySink();
    final _MemorySink metadataSink = new _MemorySink();
    final _MemorySink symbolsSink = new _MemorySink();
    final CoreTypes coreTypes = new CoreTypes(testComponent);

    await javaScriptBundler.compile(
      new ClassHierarchy(testComponent, coreTypes),
      coreTypes,
      packageConfig,
      codeSink,
      manifestSink,
      sourcemapSink,
      metadataSink,
      symbolsSink,
    );

    final String code = utf8.decode(codeSink.buffer);
    final Map<String, dynamic> manifest = json.decode(
      utf8.decode(manifestSink.buffer),
    );

    // There should be 3 modules since A, B, C are now compiled separately
    final String moduleHeader = r"define(['dart_sdk'], (function load__";
    expect(moduleHeader.allMatches(code), hasLength(3));

    // Expected module headers.
    final String aModuleHeader =
        r"define(['dart_sdk'], (function load__a_dart(dart_sdk) {";
    expect(code, contains(aModuleHeader));
    final String bModuleHeader =
        r"define(['dart_sdk'], (function load__b_dart(dart_sdk) {";
    expect(code, contains(bModuleHeader));
    final String cModuleHeader =
        r"define(['dart_sdk'], (function load__c_dart(dart_sdk) {";
    expect(code, contains(cModuleHeader));
    // Verify source map url is correct.
    expect(code, contains('sourceMappingURL=a.dart.lib.js.map'));

    final List<dynamic> offsets = manifest['/a.dart.lib.js']['sourcemap'];
    final Map<String, dynamic> sourcemapModuleA = json.decode(
      utf8.decode(sourcemapSink.buffer.sublist(offsets.first, offsets.last)),
    );

    // Verify source maps are pointing at correct source files.
    expect(sourcemapModuleA['file'], 'a.dart.lib.js');
  });

  test('can compile using the advanced invalidation', () async {
    final Uri uriC = new Uri.file('/c.dart');
    // Given 3 libraries A -> B -> C
    final Library libraryC = new Library(
      uriC,
      fileUri: uriC,
      procedures: [
        new Procedure(
          new Name('CheckForContents'),
          ProcedureKind.Method,
          new FunctionNode(new Block([])),
          fileUri: uriC,
        ),
      ],
    );
    final Uri uriB = new Uri.file('/b.dart');
    final Library libraryB = new Library(uriB, fileUri: uriB);
    libraryB.dependencies.add(new LibraryDependency.import(libraryC));
    final Uri uriA = new Uri.file('/a.dart');
    final Library libraryA = new Library(
      uriA,
      fileUri: uriA,
      dependencies: [new LibraryDependency.import(libraryB)],
      procedures: [
        new Procedure(
          new Name('ArbitrarilyChosen'),
          ProcedureKind.Method,
          new FunctionNode(new Block([])),
          fileUri: uriA,
        ),
      ],
    );
    final Component testComponent = new Component(
      libraries: [libraryA, libraryB, libraryC, ...testCoreLibraries],
    );

    final IncrementalJavaScriptBundler javaScriptBundler =
        new IncrementalJavaScriptBundler(null, {}, multiRootScheme);

    await javaScriptBundler.initialize(testComponent, uriA, packageConfig);

    // Create a new component that only contains C.
    final Library libraryC2 = new Library(
      uriC,
      fileUri: uriC,
      procedures: [
        new Procedure(
          new Name('AlternativeContents'),
          ProcedureKind.Method,
          new FunctionNode(new Block([])),
          fileUri: uriC,
        ),
      ],
    );

    final Component partialComponent = new Component(libraries: [libraryC2]);

    await javaScriptBundler.invalidate(
      partialComponent,
      testComponent,
      uriA,
      packageConfig,
      recompileRestart: false,
    );

    final _MemorySink manifestSink = new _MemorySink();
    final _MemorySink codeSink = new _MemorySink();
    final _MemorySink sourcemapSink = new _MemorySink();
    final _MemorySink metadataSink = new _MemorySink();
    final _MemorySink symbolsSink = new _MemorySink();
    final CoreTypes coreTypes = new CoreTypes(testComponent);

    await javaScriptBundler.compile(
      new ClassHierarchy(testComponent, coreTypes),
      coreTypes,
      packageConfig,
      codeSink,
      manifestSink,
      sourcemapSink,
      metadataSink,
      symbolsSink,
    );

    final String code = utf8.decode(codeSink.buffer);

    // There should be only a single module.
    final String moduleHeader = r"define(['dart_sdk'], (function load__";
    expect(moduleHeader.allMatches(code), hasLength(1));

    // C source code should be updated.
    expect(code, contains('AlternativeContents'));
  });
}

class _MemorySink implements IOSink {
  final List<int> buffer = <int>[];

  @override
  void add(List<int> data) {
    buffer.addAll(data);
  }

  @override
  Future<void> close() => new Future.value();

  @override
  void noSuchMethod(Invocation invocation) {
    throw new UnsupportedError(invocation.memberName.toString());
  }
}

Map<String, List<String>> _combineMaps(
  Map<String, List<String>> left,
  Map<String, List<String>> right,
) {
  final Map<String, List<String>> result = new Map<String, List<String>>.of(
    left,
  );
  for (String key in right.keys) {
    (result[key] ??= []).addAll(right[key]!);
  }
  return result;
}
