// 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.

import 'dart:async';
import 'dart:convert';

import 'package:front_end/src/api_prototype/byte_store.dart';
import 'package:front_end/src/api_prototype/file_system.dart';
import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart';
import 'package:front_end/src/base/api_signature.dart';
import 'package:front_end/src/base/performance_logger.dart';
import 'package:front_end/src/base/processed_options.dart';
import 'package:front_end/src/fasta/compiler_context.dart';
import 'package:front_end/src/fasta/dill/dill_target.dart';
import 'package:front_end/src/fasta/kernel/kernel_target.dart';
import 'package:front_end/src/fasta/ticker.dart';
import 'package:front_end/src/fasta/uri_translator.dart';
import 'package:front_end/src/incremental/file_state.dart';
import 'package:front_end/src/incremental/reference_index.dart';
import 'package:kernel/kernel.dart';
import 'package:meta/meta.dart';

/// Implementation of [IncrementalKernelGenerator].
///
/// The initial compilation of the entry point is performed not incrementally.
///
/// Each file that is transitively referenced from the entry point is read,
/// its API signature is computed.  Then full compilation is performed, without
/// any incrementality, to get the initial program.  When a file is invalidated,
/// it is read again, and its API signature is recomputed.  If the API signature
/// is the same as it was before, then only the library of the file is
/// recompiled, and the current program is updated.  If the API signature of
/// a file is different, all libraries that transitively use the changed file
/// are removed from the current program, and recompiled using the remaining
/// libraries.
class IncrementalKernelGeneratorImpl implements IncrementalKernelGenerator {
  static const MSG_PENDING_COMPUTE =
      'A computeDelta() invocation is still executing.';

  static const MSG_NO_LAST_DELTA =
      'The last delta has been already accepted or rejected.';

  static const MSG_HAS_LAST_DELTA =
      'The last delta must be either accepted or rejected.';

  /// The version of data format, should be incremented on every format change.
  static const int DATA_VERSION = 1;

  /// Options used by the kernel compiler.
  final ProcessedOptions options;

  /// The optional SDK outline as a serialized program.
  /// If provided, the driver will not attempt to read SDK files.
  final List<int> _sdkOutlineBytes;

  /// The [FileSystem] which should be used by the front end to access files.
  final FileSystem _fileSystem;

  /// The logger to report compilation progress.
  final PerformanceLog _logger;

  /// The [ByteStore] used to cache results.
  final ByteStore _byteStore;

  /// The object that knows how to resolve "package:" and "dart:" URIs.
  final UriTranslator uriTranslator;

  /// The URI of the program entry point.
  final Uri _entryPoint;

  /// The function to notify when files become used or unused, or `null`.
  final WatchUsedFilesFn _watchFn;

  /// The salt to mix into all hashes used as keys for serialized data.
  List<int> _salt;

  /// The current file system state.
  FileSystemState _fsState;

  /// The list of absolute file URIs that were reported through [invalidate]
  /// and not checked for actual changes yet.
  List<Uri> _invalidatedFiles = [];

  /// The set of libraries for which the content of the library file, or
  /// one of its parts, changed using [invalidate], and during
  /// [_refreshInvalidatedFiles] it was found that that changes are only in
  /// method bodies.
  ///
  /// If any library had an API change, this set will be empty.
  final Set<FileState> _changedLibrariesWithSameApi = new Set<FileState>();

  /// The [Program] with currently valid libraries. When a file is invalidated,
  /// we remove the file, its library, and everything affected from [_program].
  Program _program = new Program();

  /// The [DillTarget] that represents the current [Program] state.
  DillTarget _dillTarget;

  /// Each key is the file system URI of a library.
  /// Each value is the libraries that directly depend on the key library.
  Map<Uri, Set<Uri>> _directLibraryDependencies = {};

  /// Each key is the file system URI of a library.
  /// Each value is the [Library] that is still in the [_program].
  Map<Uri, Library> _uriToLibrary = {};

  /// Each key is the file system URI of a part.
  /// Each value is the file system URI of the library that sources the part.
  Map<Uri, Uri> _partToLibrary = {};

  /// The index that keeps track of references and nodes that use them,
  /// and allows fast reference replacement on a single library compilation.
  final ReferenceIndex _referenceIndex = new ReferenceIndex();

  /// Whether [computeDelta] is executing.
  bool _isComputeDeltaExecuting = false;

  /// The current signatures for libraries.
  final Map<Uri, String> _currentSignatures = {};

  /// The signatures for libraries produced by the last [computeDelta], or
  /// `null` if the last delta was either accepted or rejected.
  Map<Uri, String> _lastSignatures;

  /// The object that provides additional information for tests.
  final _TestView _testView = new _TestView();

  IncrementalKernelGeneratorImpl(this.options, this.uriTranslator,
      List<int> sdkOutlineBytes, this._entryPoint,
      {WatchUsedFilesFn watch})
      : _sdkOutlineBytes = sdkOutlineBytes,
        _fileSystem = options.fileSystem,
        _logger = options.logger,
        _byteStore = options.byteStore,
        _watchFn = watch {
    _computeSalt();

    Future<Null> onFileAdded(Uri uri) {
      if (_watchFn != null) {
        return _watchFn(uri, true);
      }
      return new Future.value();
    }

    _fsState = new FileSystemState(_byteStore, _fileSystem, options.target,
        uriTranslator, _salt, onFileAdded);

    // Pre-populate the Program with SDK.
    _loadSdkOutline();

    _createDillTarget();
  }

  /// Return the object that provides additional information for tests.
  @visibleForTesting
  _TestView get test => _testView;

  @override
  void acceptLastDelta() {
    _throwIfNoLastDelta();
    _currentSignatures.addAll(_lastSignatures);
    _lastSignatures = null;
  }

  @override
  Future<DeltaProgram> computeDelta() {
    if (_isComputeDeltaExecuting) {
      throw new StateError(MSG_PENDING_COMPUTE);
    }

    if (_lastSignatures != null) {
      throw new StateError(MSG_HAS_LAST_DELTA);
    }
    _lastSignatures = {};

    _isComputeDeltaExecuting = true;

    return _runWithFrontEndContext('Compute delta', () async {
      try {
        await _refreshInvalidatedFiles();
        _testView.compiledUris.clear();

        // Ensure that the graph starting at the entry point is ready.
        await _logger.runAsync('Build graph of files', () async {
          return await _fsState.getFile(_entryPoint);
        });

        // The file graph might have changed, perform GC.
        await _gc();

        // Compile just libraries with changes to function bodies, or
        // compile multiple libraries because of API changes.
        if (_changedLibrariesWithSameApi.isNotEmpty) {
          await _logger.runAsync('Compile libraries with body changes',
              () async {
            await _compileLibrariesWithBodyChanges();
          });
        } else {
          _createDillTarget();

          // Append all libraries what we still have in the current program.
          Set<Uri> validLibraries =
              _program.libraries.map((library) => library.importUri).toSet();
          var validDillCount = validLibraries.length;
          await _logger.runAsync('Load $validDillCount dill libraries',
              () async {
            _dillTarget.loader.appendLibraries(_program);
            await _dillTarget.buildOutlines();
          });

          // Configure KernelTarget to compile the entry point.
          var kernelTarget =
              new KernelTarget(_fileSystem, false, _dillTarget, uriTranslator);
          kernelTarget.read(_entryPoint);

          // Compile the entry point.
          await _logger.runAsync('Compile', () async {
            await kernelTarget.buildOutlines(nameRoot: _program.root);
            _program = await kernelTarget.buildProgram() ?? _program;
          });
          _program.computeCanonicalNames();

          _logger.run('Compute dependencies', _computeDependencies);

          // Append new libraries to the DillTarget.
          int newDillCount = _program.libraries.length - validDillCount;
          await _logger.runAsync('Append $newDillCount dill libraries',
              () async {
            _dillTarget.loader.appendLibraries(_program,
                filter: (uri) => !validLibraries.contains(uri));
            await _dillTarget.buildOutlines();
          });
        }

        _logger.run('Index references', () {
          _referenceIndex.indexNewLibraries(_program);
        });

        // Prepare libraries that changed relatively to the current state.
        var changedLibraries = new Set<Uri>();
        for (var library in _program.libraries) {
          var uri = library.importUri;
          var file = _fsState.getFileOrNull(uri);
          if (file != null && _currentSignatures[uri] != file.signatureStr) {
            changedLibraries.add(library.fileUri);
            _lastSignatures[uri] = file.signatureStr;
            _testView.compiledUris.add(uri);
          }
        }

        // The set of affected library cycles (have different signatures),
        // or libraries that import or export affected libraries (so VM might
        // have inlined some code from affected libraries into them).
        final vmRequiredLibraries = new Set<Uri>();

        void gatherVmRequiredLibraries(Uri libraryUri) {
          if (vmRequiredLibraries.add(libraryUri)) {
            var directUsers = _directLibraryDependencies[libraryUri];
            directUsers?.forEach(gatherVmRequiredLibraries);
          }
        }

        changedLibraries.forEach(gatherVmRequiredLibraries);

        // Compose the resulting program with new libraries.
        var program = new Program(nameRoot: _program.root);
        for (var library in _program.libraries) {
          if (_sdkOutlineBytes != null && library.importUri.isScheme('dart')) {
            continue;
          }
          if (vmRequiredLibraries.contains(library.fileUri)) {
            program.uriToSource[library.fileUri] =
                _program.uriToSource[library.fileUri];
            for (var part in library.parts) {
              program.uriToSource[part.fileUri] =
                  _program.uriToSource[part.fileUri];
            }
            program.libraries.add(library);
            library.parent = program;
          }
        }
        program.mainMethod = _program.mainMethod;
        _logger.writeln('Returning ${program.libraries.length} libraries.');
        _logger.writeln('There are ${_dillTarget.loader.libraries.length} '
            'libraries in DillTarget.');

        var stateString = _ExternalState.asString(_lastSignatures);
        return new DeltaProgram(stateString, program);
      } finally {
        _isComputeDeltaExecuting = false;
      }
    });
  }

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

  @override
  void rejectLastDelta() {
    _throwIfNoLastDelta();
    _lastSignatures = null;
  }

  @override
  void reset() {
    _currentSignatures.clear();
    _lastSignatures = null;
  }

  @override
  void setState(String state) {
    if (_isComputeDeltaExecuting) {
      throw new StateError(MSG_PENDING_COMPUTE);
    }
    var signatures = _ExternalState.fromString(state);
    _currentSignatures.clear();
    _currentSignatures.addAll(signatures);
  }

  /// The [_program] is almost valid, there are [_changedLibrariesWithSameApi]
  /// which should be recompiled, but all other libraries are fine.
  ///
  /// Compile the changed libraries and update referenced in other libraries.
  Future<Null> _compileLibrariesWithBodyChanges() async {
    if (_changedLibrariesWithSameApi.isNotEmpty) {
      var kernelTarget =
          new KernelTarget(_fileSystem, false, _dillTarget, uriTranslator);

      // Schedule URIs of changed libraries for compilation.
      for (var changedLibrary in _changedLibrariesWithSameApi) {
        _testView.compiledUris.add(changedLibrary.uri);
        // Detach the old library.
        var oldLibrary = _uriToLibrary[changedLibrary.fileUri];
        _program.root.removeChild(changedLibrary.uriStr);
        _program.libraries.remove(oldLibrary);
        _dillTarget.loader.builders.remove(changedLibrary.uri);
        _dillTarget.loader.libraries.remove(oldLibrary);
        _referenceIndex.removeLibrary(oldLibrary);
        // Schedule the library for compilation.
        kernelTarget.read(changedLibrary.uri);
      }

      var mainReference = _program.mainMethodName;
      await _logger.runAsync('Compile', () async {
        await kernelTarget.buildOutlines(nameRoot: _program.root);
        await kernelTarget.buildProgram();
      });

      // Attach the new library and replace references.
      _logger.run('Replace references', () {
        var builders = kernelTarget.loader.builders;
        for (var changedLibrary in _changedLibrariesWithSameApi) {
          Library oldLibrary = _uriToLibrary[changedLibrary.fileUri];
          Library newLibrary = builders[changedLibrary.uri].target;

          _program.root
              .getChildFromUri(newLibrary.importUri)
              .bindTo(newLibrary.reference);
          newLibrary.computeCanonicalNames();

          _program.root.adoptChild(newLibrary.canonicalName);
          _program.libraries.add(newLibrary);

          _uriToLibrary[changedLibrary.fileUri] = newLibrary;
          _referenceIndex.replaceLibrary(oldLibrary, newLibrary);

          // Schedule the new outline for loading.
          // TODO(scheglov): Add a more efficient API to add one library.
          _dillTarget.loader.appendLibraries(_program,
              filter: (uri) => uri == newLibrary.importUri);

          // If main() was defined in the recompiled library, replace it.
          if (mainReference?.asProcedure?.enclosingLibrary == oldLibrary) {
            mainReference = newLibrary.procedures
                .singleWhere((p) => p.name.name == 'main')
                .reference;
          }
        }
      });

      // Load outlines of replaced libraries.
      await _dillTarget.buildOutlines();

      // Restore the main() procedure reference.
      _program.mainMethodName = mainReference;
    }
  }

  /// Recompute [_directLibraryDependencies] for the current [_program].
  void _computeDependencies() {
    _directLibraryDependencies.clear();
    _uriToLibrary.clear();
    _partToLibrary.clear();

    var processedLibraries = new Set<Library>();

    void processLibrary(Library library) {
      if (!processedLibraries.add(library)) return;
      _uriToLibrary[library.fileUri] = library;

      // Remember libraries for parts.
      for (var part in library.parts) {
        _partToLibrary[part.fileUri] = library.fileUri;
      }

      // Record reverse dependencies.
      for (LibraryDependency dependency in library.dependencies) {
        Library targetLibrary = dependency.targetLibrary;
        _directLibraryDependencies
            .putIfAbsent(targetLibrary.fileUri, () => new Set<Uri>())
            .add(library.fileUri);
        processLibrary(targetLibrary);
      }
    }

    var entryPointLibrary =
        _program.libraries.singleWhere((lib) => lib.importUri == _entryPoint);
    processLibrary(entryPointLibrary);
  }

  /// Compute salt and put into [_salt].
  void _computeSalt() {
    var saltBuilder = new ApiSignature();
    saltBuilder.addInt(DATA_VERSION);
    saltBuilder.addBool(options.strongMode);
    if (_sdkOutlineBytes != null) {
      saltBuilder.addBytes(_sdkOutlineBytes);
    }
    _salt = saltBuilder.toByteList();
  }

  /// Create a new, empty [_dillTarget].
  void _createDillTarget() {
    _dillTarget = new DillTarget(
        new Ticker(isVerbose: false), uriTranslator, options.target);
  }

  /// Find files which are not referenced from the entry point and report
  /// them to the watch function.
  Future<Null> _gc() async {
    List<FileState> removedFiles = _fsState.gc(_entryPoint);
    if (removedFiles.isNotEmpty && _watchFn != null) {
      for (var removedFile in removedFiles) {
        // If a library, remove it from the program.
        Library library = _uriToLibrary.remove(removedFile.fileUri);
        if (library != null) {
          _currentSignatures.remove(library.importUri);
          _program.libraries.remove(library);
          _program.root.removeChild(library.importUri.toString());
          _program.uriToSource.remove(library.fileUri);
          for (var part in library.parts) {
            _program.uriToSource.remove(part.fileUri);
          }
        }
        // Notify the client.
        await _watchFn(removedFile.fileUri, false);
      }
    }
  }

  /// If SDK outline bytes are provided, load it and configure the file system
  /// state to skip SDK library files.
  void _loadSdkOutline() {
    if (_sdkOutlineBytes != null) {
      _logger.run('Load SDK outline from bytes', () {
        loadProgramFromBytes(_sdkOutlineBytes, _program);
        // Configure the file system state to skip the outline libraries.
        for (var outlineLibrary in _program.libraries) {
          _fsState.skipSdkLibraries.add(outlineLibrary.importUri);
        }
      });
    }
  }

  /// Refresh all the invalidated files and update dependencies.
  Future<Null> _refreshInvalidatedFiles() async {
    await _logger.runAsync('Refresh invalidated files', () async {
      // Replace the list to avoid concurrent modifications.
      List<Uri> invalidatedFiles = _invalidatedFiles;
      _invalidatedFiles = <Uri>[];

      // Refresh the files.
      _changedLibrariesWithSameApi.clear();
      var filesWithDifferentApiSignature = <FileState>[];
      for (var fileUri in invalidatedFiles) {
        var file = _fsState.getFileByFileUri(fileUri);
        if (file != null) {
          _logger.writeln('Refresh $fileUri');
          bool apiSignatureChanged = await file.refresh();
          if (apiSignatureChanged) {
            filesWithDifferentApiSignature.add(file);
          } else {
            FileState libraryFile = file;
            Uri libraryFileUri = _partToLibrary[file.fileUri];
            if (libraryFileUri != null) {
              libraryFile = _fsState.getFileByFileUri(libraryFileUri);
            }
            _changedLibrariesWithSameApi.add(libraryFile);
          }
        }
      }

      if (filesWithDifferentApiSignature.isNotEmpty) {
        _logger.writeln('API changed in $filesWithDifferentApiSignature.');
        _changedLibrariesWithSameApi.clear();

        /// Invalidate the library with the given [libraryUri],
        /// and recursively all its clients.
        void invalidateLibrary(Uri libraryUri) {
          Library library = _uriToLibrary.remove(libraryUri);
          if (library == null) return;

          // Invalidate the library.
          _program.libraries.remove(library);
          _program.root.removeChild(library.importUri.toString());
          _program.uriToSource.remove(libraryUri);
          _currentSignatures.remove(library.importUri);
          _referenceIndex.removeLibrary(library);

          // Recursively invalidate clients.
          Set<Uri> directDependencies =
              _directLibraryDependencies.remove(libraryUri);
          directDependencies?.forEach(invalidateLibrary);
        }

        // TODO(scheglov): Some changes still might be incremental.
        for (var uri in invalidatedFiles) {
          Uri libraryUri = _partToLibrary.remove(uri) ?? uri;
          invalidateLibrary(libraryUri);
        }
      }
    });
  }

  Future<T> _runWithFrontEndContext<T>(String msg, Future<T> f()) async {
    return await CompilerContext.runWithOptions(options, (context) {
      context.disableColors();
      return _logger.runAsync(msg, f);
    });
  }

  /// Throw [StateError] if [_lastSignatures] is `null`, i.e. there is no
  /// last delta - it either has not been computed yet, or has been already
  /// accepted or rejected.
  void _throwIfNoLastDelta() {
    if (_isComputeDeltaExecuting) {
      throw new StateError(MSG_PENDING_COMPUTE);
    }
    if (_lastSignatures == null) {
      throw new StateError(MSG_NO_LAST_DELTA);
    }
  }
}

class _ExternalState {
  /// Return the JSON encoding of the [signatures].
  static String asString(Map<Uri, String> signatures) {
    var json = <String, String>{};
    signatures.forEach((uri, signature) {
      json[uri.toString()] = signature;
    });
    return JSON.encode(json);
  }

  /// Decode the given JSON [state] into the program state.
  static Map<Uri, String> fromString(String state) {
    var signatures = <Uri, String>{};
    Map<String, String> json = JSON.decode(state);
    json.forEach((uriStr, signature) {
      var uri = Uri.parse(uriStr);
      signatures[uri] = signature;
    });
    return signatures;
  }
}

@visibleForTesting
class _TestView {
  /// The list of [Uri]s compiled for the last delta.
  /// It does not include libraries which were reused from the last program.
  final Set<Uri> compiledUris = new Set<Uri>();
}
