// 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/src/kernel/compiler.dart' show ProgramCompiler;
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, List<String>> additionalRequiredClasses = {
  'dart:core': ['Comparable'],
  'dart:async': [
    'StreamIterator',
    '_AsyncStarImpl',
  ],
  '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',
    'SyncIterable',
  ],
};

/// Additional indexed top level methods required by the dev_compiler.
final Map<String, List<String>> requiredMethods = {
  'dart:_runtime': ['assertInterop'],
};

void main() {
  final Map<String, List<String>> allRequiredTypes =
      _combineMaps(CoreTypes.requiredClasses, additionalRequiredClasses);
  final Set<String> allRequiredLibraries = {
    ...allRequiredTypes.keys,
    ...requiredMethods.keys
  };
  final List<Library> testCoreLibraries = [
    for (String requiredLibrary in allRequiredLibraries)
      new Library(Uri.parse(requiredLibrary),
          fileUri: Uri.parse(requiredLibrary),
          classes: [
            for (String requiredClass
                in allRequiredTypes[requiredLibrary] ?? [])
              new Class(
                  name: requiredClass, fileUri: Uri.parse(requiredLibrary)),
          ],
          procedures: [
            for (String requiredMethod
                in requiredMethods[requiredLibrary] ?? [])
              new Procedure(new Name(requiredMethod), ProcedureKind.Method,
                  new FunctionNode(new EmptyStatement()),
                  fileUri: Uri.parse(requiredLibrary)),
          ]),
  ];

  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 module uris for file paths', () async {
        final Uri fileUri = new Uri.file('/c.dart');

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

        final String moduleUrl =
            javaScriptBundler.urlForComponentUri(fileUri, packageConfig);
        final String moduleName = javaScriptBundler.makeModuleName(moduleUrl);
        expect(moduleUrl, '/c.dart');
        expect(moduleName, 'c.dart');
      });

      test('Creates module 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 moduleUrl =
            javaScriptBundler.urlForComponentUri(packageUri, packageConfig);
        final String moduleName = javaScriptBundler.makeModuleName(moduleUrl);
        expect(moduleUrl,
            debuggerNames ? 'packages/a/lib/a.dart' : '/packages/a/a.dart');
        expect(moduleName,
            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, ProgramCompiler> 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.
        final String moduleUrl = javaScriptBundler.urlForComponentUri(
            library.importUri, packageConfig);
        final String moduleName = javaScriptBundler.makeModuleName(moduleUrl);
        expect(compilers.keys, equals([moduleName]));
      });

      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 moduleUrl = javaScriptBundler.urlForComponentUri(
            library.importUri, packageConfig);

        expect(manifest, {
          '$moduleUrl.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 modules 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);

    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);

    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;
}
