// Copyright (c) 2017, 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 fasta.incremental_compiler;

import 'dart:async' show Future;

import 'package:kernel/kernel.dart' show Program, loadProgramFromBytes;

import '../api_prototype/incremental_kernel_generator.dart'
    show DeltaProgram, IncrementalKernelGenerator;

import 'builder/builder.dart' show LibraryBuilder;

import 'dill/dill_target.dart' show DillTarget;

import 'kernel/kernel_target.dart' show KernelTarget;

import 'source/source_graph.dart' show SourceGraph;

import 'source/source_library_builder.dart' show SourceLibraryBuilder;

import 'compiler_context.dart' show CompilerContext;

import 'problems.dart' show unsupported;

import 'ticker.dart' show Ticker;

import 'uri_translator.dart' show UriTranslator;

abstract class DeprecatedIncrementalKernelGenerator
    implements IncrementalKernelGenerator {
  /// This does nothing. It will be deprecated.
  @override
  void acceptLastDelta() {}

  /// Always throws an error. Will be deprecated.
  @override
  void rejectLastDelta() => unsupported("rejectLastDelta", -1, null);

  /// Always throws an error. Will be deprecated.
  @override
  void reset() => unsupported("rejectLastDelta", -1, null);

  /// Always throws an error. Will be deprecated.
  @override
  void setState(String state) => unsupported("setState", -1, null);
}

abstract class DeprecatedDeltaProgram implements DeltaProgram {
  @override
  String get state => unsupported("state", -1, null);
}

class FastaDelta extends DeprecatedDeltaProgram {
  @override
  final Program newProgram;

  FastaDelta(this.newProgram);
}

class IncrementalCompiler extends DeprecatedIncrementalKernelGenerator {
  final CompilerContext context;

  final Ticker ticker;

  List<Uri> invalidatedUris = <Uri>[];

  DillTarget platform;

  KernelTarget userCode;

  IncrementalCompiler(this.context) : ticker = context.options.ticker;

  @override
  Future<FastaDelta> computeDelta({Uri entryPoint}) async {
    ticker.reset();
    return context.runInContext<Future<FastaDelta>>((CompilerContext c) async {
      if (platform == null) {
        UriTranslator uriTranslator = await c.options.getUriTranslator();
        ticker.logMs("Read packages file");

        platform = new DillTarget(ticker, uriTranslator, c.options.target);
        List<int> bytes = await c.options.loadSdkSummaryBytes();
        if (bytes != null) {
          ticker.logMs("Read ${c.options.sdkSummary}");
          Program program = loadProgramFromBytes(bytes);
          ticker.logMs("Deserialized ${c.options.sdkSummary}");
          platform.loader.appendLibraries(program, byteCount: bytes.length);
          ticker.logMs("Appended libraries");
        }
        await platform.buildOutlines();
      }

      List<Uri> invalidatedUris = this.invalidatedUris.toList();
      this.invalidatedUris.clear();

      List<LibraryBuilder> reusedLibraries =
          computeReusedLibraries(invalidatedUris);
      ticker.logMs("Decided to reuse ${reusedLibraries.length} libraries");

      userCode = new KernelTarget(
          c.fileSystem, false, platform, platform.uriTranslator,
          uriToSource: c.uriToSource);
      for (LibraryBuilder library in reusedLibraries) {
        userCode.loader.builders[library.uri] = library;
      }

      userCode.read(entryPoint);

      await userCode.buildOutlines();

      return new FastaDelta(
          await userCode.buildProgram(verify: c.options.verify));
    });
  }

  List<LibraryBuilder> computeReusedLibraries(Iterable<Uri> invalidatedUris) {
    if (userCode == null) return const <LibraryBuilder>[];

    // [invalidatedUris] converted to a set.
    Set<Uri> invalidatedFileUris = invalidatedUris.toSet();

    // Maps all non-platform LibraryBuilders from their import URI.
    Map<Uri, LibraryBuilder> builders = <Uri, LibraryBuilder>{};

    // Invalidated URIs translated back to their import URI (package:, dart:,
    // etc.).
    List<Uri> invalidatedImportUris = <Uri>[];

    // Compute [builders] and [invalidatedImportUris].
    userCode.loader.builders.forEach((Uri uri, LibraryBuilder library) {
      if (library.loader != platform.loader) {
        assert(library is SourceLibraryBuilder);
        builders[uri] = library;
        if (invalidatedFileUris.contains(uri) ||
            (uri != library.fileUri &&
                invalidatedFileUris.contains(library.fileUri))) {
          invalidatedImportUris.add(uri);
        }
      }
    });

    SourceGraph graph = new SourceGraph(builders);

    // Compute direct dependencies for each import URI (the reverse of the
    // edges returned by `graph.neighborsOf`).
    Map<Uri, Set<Uri>> directDependencies = <Uri, Set<Uri>>{};
    for (Uri vertex in graph.vertices) {
      for (Uri neighbor in graph.neighborsOf(vertex)) {
        (directDependencies[neighbor] ??= new Set<Uri>()).add(vertex);
      }
    }

    // Remove all dependencies of [invalidatedImportUris] from builders.
    List<Uri> workList = invalidatedImportUris;
    while (workList.isNotEmpty) {
      LibraryBuilder current = builders.remove(workList.removeLast());
      // [current] is null if the corresponding key (URI) has already been
      // removed.
      if (current != null) {
        Set<Uri> s = directDependencies[current.uri];
        if (s != null) {
          // [s] is null for leaves.
          for (Uri dependency in s) {
            workList.add(dependency);
          }
        }
      }
    }

    return builders.values.toList();
  }

  @override
  void invalidate(Uri uri) {
    invalidatedUris.add(uri);
  }
}
