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

library dart2js.test.memory_compiler;

import 'dart:async';

import 'package:compiler/compiler.dart' show DiagnosticHandler;
import 'package:compiler/compiler_new.dart'
    show
        CompilationResult,
        CompilerDiagnostics,
        CompilerOutput,
        Diagnostic,
        PackagesDiscoveryProvider;
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/diagnostics/messages.dart' show Message;
import 'package:compiler/src/elements/entities.dart'
    show LibraryEntity, MemberEntity;
import 'package:compiler/src/enqueue.dart' show ResolutionEnqueuer;
import 'package:compiler/src/null_compiler_output.dart' show NullCompilerOutput;
import 'package:compiler/src/library_loader.dart'
    show LoadedLibraries, KernelLibraryLoaderTask;
import 'package:compiler/src/options.dart' show CompilerOptions;

import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
import 'package:front_end/src/compute_platform_binaries_location.dart'
    show computePlatformBinariesLocation;

import 'memory_source_file_helper.dart';

export 'output_collector.dart';
export 'package:compiler/compiler_new.dart' show CompilationResult;
export 'diagnostic_helper.dart';

class MultiDiagnostics implements CompilerDiagnostics {
  final List<CompilerDiagnostics> diagnosticsList;

  const MultiDiagnostics([this.diagnosticsList = const []]);

  @override
  void report(covariant Message message, Uri uri, int begin, int end,
      String text, Diagnostic kind) {
    for (CompilerDiagnostics diagnostics in diagnosticsList) {
      diagnostics.report(message, uri, begin, end, text, kind);
    }
  }
}

CompilerDiagnostics createCompilerDiagnostics(
    CompilerDiagnostics diagnostics, SourceFileProvider provider,
    {bool showDiagnostics: true, bool verbose: false}) {
  CompilerDiagnostics handler = diagnostics;
  if (showDiagnostics) {
    if (diagnostics == null) {
      handler = new FormattingDiagnosticHandler(provider)
        ..verbose = verbose
        ..autoReadFileUri = true;
    } else {
      var formattingHandler = new FormattingDiagnosticHandler(provider)
        ..verbose = verbose
        ..autoReadFileUri = true;
      handler = new MultiDiagnostics([diagnostics, formattingHandler]);
    }
  } else if (diagnostics == null) {
    handler = new MultiDiagnostics();
  }
  return handler;
}

Expando<MemorySourceFileProvider> expando =
    new Expando<MemorySourceFileProvider>();

// Cached kernel state for non-strong mode.
fe.InitializedCompilerState kernelInitializedCompilerState;

// Cached kernel state for strong mode.
fe.InitializedCompilerState strongKernelInitializedCompilerState;

/// memorySourceFiles can contain a map of string filename to string file
/// contents or string file name to binary file contents (hence the `dynamic`
/// type for the second parameter).
Future<CompilationResult> runCompiler(
    {Map<String, dynamic> memorySourceFiles: const <String, dynamic>{},
    Uri entryPoint,
    List<Uri> entryPoints,
    List<Uri> resolutionInputs,
    CompilerDiagnostics diagnosticHandler,
    CompilerOutput outputProvider,
    List<String> options: const <String>[],
    CompilerImpl cachedCompiler,
    bool showDiagnostics: true,
    Uri packageRoot,
    Uri packageConfig,
    PackagesDiscoveryProvider packagesDiscoveryProvider,
    void beforeRun(CompilerImpl compiler)}) async {
  if (entryPoint == null) {
    entryPoint = Uri.parse('memory:main.dart');
  }
  CompilerImpl compiler = compilerFor(
      entryPoint: entryPoint,
      resolutionInputs: resolutionInputs,
      memorySourceFiles: memorySourceFiles,
      diagnosticHandler: diagnosticHandler,
      outputProvider: outputProvider,
      options: options,
      cachedCompiler: cachedCompiler,
      showDiagnostics: showDiagnostics,
      packageRoot: packageRoot,
      packageConfig: packageConfig,
      packagesDiscoveryProvider: packagesDiscoveryProvider);
  compiler.librariesToAnalyzeWhenRun = entryPoints;
  if (beforeRun != null) {
    beforeRun(compiler);
  }
  fe.InitializedCompilerState compilerState;
  bool isSuccess = await compiler.run(entryPoint);
  if (compiler.libraryLoader is KernelLibraryLoaderTask) {
    KernelLibraryLoaderTask loader = compiler.libraryLoader;
    if (compiler.options.strongMode) {
      compilerState = strongKernelInitializedCompilerState =
          loader.initializedCompilerState;
    } else {
      compilerState =
          kernelInitializedCompilerState = loader.initializedCompilerState;
    }
  }
  return new CompilationResult(compiler,
      isSuccess: isSuccess, kernelInitializedCompilerState: compilerState);
}

CompilerImpl compilerFor(
    {Uri entryPoint,
    List<Uri> resolutionInputs,
    Map<String, dynamic> memorySourceFiles: const <String, dynamic>{},
    CompilerDiagnostics diagnosticHandler,
    CompilerOutput outputProvider,
    List<String> options: const <String>[],
    CompilerImpl cachedCompiler,
    bool showDiagnostics: true,
    Uri packageRoot,
    Uri packageConfig,
    PackagesDiscoveryProvider packagesDiscoveryProvider}) {
  Uri libraryRoot = Uri.base.resolve('sdk/');
  Uri platformBinaries;
  if (!options.contains(Flags.useOldFrontend)) {
    platformBinaries = computePlatformBinariesLocation();
  }

  if (packageRoot == null &&
      packageConfig == null &&
      packagesDiscoveryProvider == null) {
    if (Platform.packageRoot != null) {
      packageRoot = Uri.base.resolve(Platform.packageRoot);
    } else if (Platform.packageConfig != null) {
      packageConfig = Uri.base.resolve(Platform.packageConfig);
    } else {
      // The tests are run with the base directory as the SDK root
      // so just use the .packages file there.
      packageConfig = Uri.base.resolve('.packages');
    }
  }

  MemorySourceFileProvider provider;
  if (cachedCompiler == null) {
    provider = new MemorySourceFileProvider(memorySourceFiles);
    // Saving the provider in case we need it later for a cached compiler.
    expando[provider] = provider;
  } else {
    // When using a cached compiler, it has read a number of files from disk
    // already (and will not attempt to read them again due to caching). These
    // files must be available to the new diagnostic handler.
    provider = expando[cachedCompiler.provider];
    provider.memorySourceFiles = memorySourceFiles;
  }
  diagnosticHandler = createCompilerDiagnostics(diagnosticHandler, provider,
      showDiagnostics: showDiagnostics,
      verbose: options.contains('-v') || options.contains('--verbose'));

  if (outputProvider == null) {
    outputProvider = const NullCompilerOutput();
  }

  CompilerOptions compilerOptions = new CompilerOptions.parse(
      entryPoint: entryPoint,
      resolutionInputs: resolutionInputs,
      libraryRoot: libraryRoot,
      packageRoot: packageRoot,
      options: options,
      environment: {},
      platformBinaries: platformBinaries,
      packageConfig: packageConfig,
      packagesDiscoveryProvider: packagesDiscoveryProvider);
  if (compilerOptions.strongMode) {
    compilerOptions.kernelInitializedCompilerState =
        strongKernelInitializedCompilerState;
  } else {
    compilerOptions.kernelInitializedCompilerState =
        kernelInitializedCompilerState;
  }
  CompilerImpl compiler = new CompilerImpl(
      provider, outputProvider, diagnosticHandler, compilerOptions);

  if (cachedCompiler != null) {
    Map copiedLibraries = {};
    cachedCompiler.libraryLoader.libraries.forEach((dynamic library) {
      if (library.isPlatformLibrary) {
        dynamic libraryLoader = compiler.libraryLoader;
        libraryLoader.mapLibrary(library);
        copiedLibraries[library.canonicalUri] = library;
      }
    });
    compiler.processLoadedLibraries(new MemoryLoadedLibraries(copiedLibraries));
    ResolutionEnqueuer resolutionEnqueuer = compiler.startResolution();

    compiler.backend.constantCompilerTask
        .copyConstantValues(cachedCompiler.backend.constantCompilerTask);

    Iterable<MemberEntity> cachedTreeElements =
        cachedCompiler.enqueuer.resolution.processedEntities;
    cachedTreeElements.forEach((MemberEntity element) {
      if (element.library.canonicalUri.scheme == 'dart') {
        resolutionEnqueuer.registerProcessedElementInternal(element);
      }
    });

    dynamic frontendStrategy = compiler.frontendStrategy;
    frontendStrategy.nativeBasicDataBuilder.reopenForTesting();

    // One potential problem that can occur when reusing elements is that there
    // is a stale reference to an old compiler object.  By nulling out the old
    // compiler's fields, such stale references are easier to identify.
    cachedCompiler.scanner = null;
    cachedCompiler.dietParser = null;
    cachedCompiler.parser = null;
    cachedCompiler.patchParser = null;
    cachedCompiler.libraryLoader = null;
    cachedCompiler.resolver = null;
    cachedCompiler.checker = null;
    cachedCompiler.globalInference = null;
    cachedCompiler.backend = null;
    // Don't null out the enqueuer as it prevents us from using cachedCompiler
    // more than once.
    cachedCompiler.deferredLoadTask = null;
    cachedCompiler.mirrorUsageAnalyzerTask = null;
    cachedCompiler.dumpInfoTask = null;
  }
  return compiler;
}

class MemoryLoadedLibraries implements LoadedLibraries {
  final Map copiedLibraries;

  MemoryLoadedLibraries(this.copiedLibraries);

  @override
  bool containsLibrary(Uri uri) => copiedLibraries.containsKey(uri);

  @override
  void forEachImportChain(f, {callback}) {
    throw new UnimplementedError();
  }

  @override
  void forEachLibrary(void f(LibraryEntity l)) =>
      copiedLibraries.values.forEach((l) => f(l));

  @override
  getLibrary(Uri uri) => copiedLibraries[uri];

  @override
  LibraryEntity get rootLibrary => copiedLibraries.values.first;
}

DiagnosticHandler createDiagnosticHandler(DiagnosticHandler diagnosticHandler,
    SourceFileProvider provider, bool showDiagnostics) {
  var handler = diagnosticHandler;
  if (showDiagnostics) {
    if (diagnosticHandler == null) {
      handler = new FormattingDiagnosticHandler(provider);
    } else {
      var formattingHandler = new FormattingDiagnosticHandler(provider);
      handler = (Uri uri, int begin, int end, String message, Diagnostic kind) {
        diagnosticHandler(uri, begin, end, message, kind);
        formattingHandler(uri, begin, end, message, kind);
      };
    }
  } else if (diagnosticHandler == null) {
    handler = (Uri uri, int begin, int end, String message, Diagnostic kind) {};
  }
  return handler;
}

main() {
  runCompiler(memorySourceFiles: {'main.dart': 'main() {}'});
}
