// 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:typed_data' show Uint8List;

import 'package:kernel/binary/ast_from_binary.dart' show SubComponentView;
import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
import 'package:kernel/kernel.dart' show Component, Library, LibraryDependency;

import '../kernel/utils.dart' show ByteSink;

// Coverage-ignore(suite): Not run.
class IncrementalSerializer {
  final Map<Uri, SerializationGroup> uriToGroup =
      new Map<Uri, SerializationGroup>();
  final Set<Uri> invalidatedUris = new Set<Uri>();

  /// Invalidate the uri: Will remove cache associated with it, depending on it
  /// etc. Called by the incremental compiler.
  void invalidate(Uri uri) {
    invalidatedUris.add(uri);
  }

  /// Initializes the cache via a already serialized list of bytes based on the
  /// view of those bytes. Called by the incremental compiler.
  bool initialize(List<int> bytes, List<SubComponentView> views) {
    if (uriToGroup.isNotEmpty) {
      throw "Cannot initialize when already in use.";
    }

    // Find the sub-components that are packaged correctly.
    List<SubComponentView> goodViews = [];
    Set<Uri> uris = new Set<Uri>();
    for (int i = 0; i < views.length; i++) {
      SubComponentView view = views[i];
      bool good = true;
      String? packageName;
      for (Library lib in view.libraries) {
        Uri uri = lib.importUri;
        // Uris need to be unique.
        if (!uris.add(lib.fileUri)) return false;
        if (uri.isScheme("package")) {
          String thisPackageName = uri.pathSegments.first;
          if (packageName == null) {
            packageName = thisPackageName;
          } else if (packageName != thisPackageName) {
            good = false;
          }
        } else {
          good = false;
        }
      }
      if (good) {
        goodViews.add(view);
      }
    }

    // Add groups. Wrap in try because an exception will be thrown if a group
    // has a dependency that isn't being met.
    try {
      List<SerializationGroup> newGroups = <SerializationGroup>[];
      for (int i = 0; i < goodViews.length; i++) {
        SubComponentView view = goodViews[i];
        Uint8List data = new Uint8List(view.componentFileSize);
        data.setRange(0, data.length, bytes, view.componentStartOffset);
        SerializationGroup newGroup = createGroupFor(view.libraries, data);
        newGroups.add(newGroup);
      }

      // Setup dependency tracking for the new groups.
      for (int i = 0; i < goodViews.length; i++) {
        SubComponentView view = goodViews[i];
        List<Library> libraries = view.libraries;
        SerializationGroup packageGroup = newGroups[i];
        setupDependencyTracking(libraries, packageGroup);
      }
    } catch (e) {
      uriToGroup.clear();
      return false;
    }
    return true;
  }

  /// Write packages to sink, cache new package data, trim input component.
  void writePackagesToSinkAndTrimComponent(
      Component? component, Sink<List<int>> sink) {
    if (component == null) return;
    if (component.libraries.isEmpty) return;

    // If we're given a partial component (i.e. an actual delta component)
    // incremental serialization (at least currently) doesn't work.
    // The reason is that it might contain a new partial thing of what we
    // already have cached while still depending on something from the same
    // group that is currently cached. We would throw away the cache, but
    // actually depend on something we just threw away --- we would try to
    // include it and crash because we no longer have it.
    // Alternative ways to fix this could be:
    // * to group into smaller groups so this wouldn't happen.
    // * cache the actual Libraries too, so we could re-serialize when needed
    //   (though maybe not eagerly).
    if (!isSelfContained(component)) return;

    // Remove cache pertaining to invalidated uris.
    if (invalidatedUris.isNotEmpty) {
      removeInvalidated();
    }

    // Make sure we can serialize individual libraries.
    component.computeCanonicalNames();

    // Split into package and non-package libraries.
    List<Library> packageLibraries = <Library>[];
    List<Library> nonPackageLibraries = <Library>[];
    for (Library lib in component.libraries) {
      Uri uri = lib.importUri;
      if (uri.isScheme("package")) {
        packageLibraries.add(lib);
      } else {
        nonPackageLibraries.add(lib);
      }
    }

    // Output already serialized packages and group needed non-serialized
    // packages.
    Map<String, List<Library>> newPackages = new Map<String, List<Library>>();
    Set<SerializationGroup> cachedPackagesInOutput =
        new Set<SerializationGroup>.identity();
    for (Library lib in packageLibraries) {
      SerializationGroup? group = uriToGroup[lib.fileUri];
      if (group != null) {
        addDataButNotDependentData(group, cachedPackagesInOutput, sink);
      } else {
        String package = lib.importUri.pathSegments.first;
        (newPackages[package] ??= <Library>[]).add(lib);
      }
    }

    // Add any dependencies that wasn't added already.
    List<SerializationGroup> upFrontGroups = cachedPackagesInOutput.toList();
    for (SerializationGroup group in upFrontGroups) {
      if (group.dependencies != null) {
        // Now also add all dependencies.
        for (SerializationGroup dep in group.dependencies!) {
          addDataAndDependentData(dep, cachedPackagesInOutput, sink);
        }
      }
    }

    // Serialize all new packages, create groups and add to sink.
    Map<String, SerializationGroup> newPackageGroups =
        new Map<String, SerializationGroup>();
    for (String package in newPackages.keys) {
      List<Library> libraries = newPackages[package]!;
      Uint8List data = serialize(component, libraries);
      sink.add(data);
      SerializationGroup newGroup = createGroupFor(libraries, data);
      newPackageGroups[package] = newGroup;
    }

    // Setup dependency tracking for the new groups.
    for (String package in newPackages.keys) {
      List<Library> libraries = newPackages[package]!;
      SerializationGroup packageGroup = newPackageGroups[package]!;
      setupDependencyTracking(libraries, packageGroup);
    }

    // All packages have been added to the sink already.
    component.libraries
      ..clear()
      ..addAll(nonPackageLibraries);
  }

  bool isSelfContained(Component component) {
    Set<Library> got = new Set<Library>.of(component.libraries);
    for (Library lib in component.libraries) {
      for (LibraryDependency dependency in lib.dependencies) {
        if (!got.contains(dependency.targetLibrary)) {
          if (dependency.targetLibrary.importUri.isScheme("dart")) {
            continue;
          }
          return false;
        }
      }
    }
    return true;
  }

  /// Remove cached data based on what has been invalidated.
  /// Note that invalidating a single file can remove many cached things because
  /// of dependencies.
  void removeInvalidated() {
    // Remove all directly invalidated entries.
    Set<SerializationGroup> removed = new Set<SerializationGroup>();
    List<SerializationGroup> workList = <SerializationGroup>[];
    for (Uri uri in invalidatedUris) {
      removeUriFromMap(uri, removed, workList);
    }

    // Continuously remove all that depend on the removed groups.
    //
    // Note that with the current invalidating strategy in the incremental
    // compiler this is not strictly necessary (assuming the incremental
    // compiler is used via the incremental compiler) - but it is included for
    // completeness.
    //
    // The reason we have to do this (assuming a different incremental
    // compiler invalidation strategy), is that we group things into packages,
    // meaning that a group as a whole might depend on another group containing
    // libraries that is not in the input component. Not removing these groups
    // could lead to including a group in an output where we cannot re-create
    // the dependencies. Example:
    // Group #1: [lib1]
    // Group #2: [lib2, lib3]. Note that lib3 depends on lib1, but lib2 is
    //                         standalone.
    // Lib1 is invalidated and we thus remove group #1.
    // We then serialize something that needs lib2. We thus output group #2.
    // We should now also output group #1, but we don't have it so we can't.
    // We can't re-create it either, because the input component only contains
    // lib2 as it is standalone. Had we removed group #2 too everything would
    // have been fine as we would then just serialize and cached lib2 by itself.
    while (workList.isNotEmpty) {
      SerializationGroup group = workList.removeLast();
      if (group.othersDependingOnMe == null) continue;
      for (SerializationGroup dependsOnGroup in group.othersDependingOnMe!) {
        removeUriFromMap(dependsOnGroup.uris.first, removed, workList);
      }
    }

    invalidatedUris.clear();
  }

  /// Setup dependency tracking for a single group having the specified
  /// libraries. Note that all groups this depend on has to be created prior
  /// to calling this.
  void setupDependencyTracking(
      List<Library> libraries, SerializationGroup packageGroup) {
    for (Library lib in libraries) {
      for (LibraryDependency dep in lib.dependencies) {
        Library dependencyLibrary = dep.importedLibraryReference.asLibrary;
        if (!dependencyLibrary.importUri.isScheme("package")) continue;
        Uri dependencyLibraryUri =
            dep.importedLibraryReference.asLibrary.fileUri;
        SerializationGroup? depGroup = uriToGroup[dependencyLibraryUri];
        if (depGroup == null) {
          throw "Didn't contain group for $dependencyLibraryUri";
        }
        if (depGroup == packageGroup) continue;
        packageGroup.registerDependency(depGroup);
      }
    }
  }

  /// Add the group but not its dependencies to the output if they weren't added
  /// already.
  void addDataButNotDependentData(SerializationGroup group,
      Set<SerializationGroup> cachedPackagesInOutput, Sink<List<int>> sink) {
    if (cachedPackagesInOutput.add(group)) {
      sink.add(group.serializedData);
    }
  }

  /// Add the group and its dependencies to the output if they weren't added
  /// already.
  void addDataAndDependentData(SerializationGroup group,
      Set<SerializationGroup> cachedPackagesInOutput, Sink<List<int>> sink) {
    if (cachedPackagesInOutput.add(group)) {
      sink.add(group.serializedData);
      if (group.dependencies != null) {
        // Now also add all dependencies.
        for (SerializationGroup dep in group.dependencies!) {
          addDataAndDependentData(dep, cachedPackagesInOutput, sink);
        }
      }
    }
  }

  /// Create a [SerializationGroup] for the input, setting up [uriToGroup].
  SerializationGroup createGroupFor(List<Library> libraries, Uint8List data) {
    Set<Uri> libraryUris = new Set<Uri>();
    for (Library lib in libraries) {
      libraryUris.add(lib.fileUri);
    }

    SerializationGroup newGroup = new SerializationGroup(data, libraryUris);

    for (Uri uri in libraryUris) {
      assert(!uriToGroup.containsKey(uri));
      uriToGroup[uri] = newGroup;
    }
    return newGroup;
  }

  /// Serialize the specified libraries using other needed data from the
  /// component.
  Uint8List serialize(Component component, List<Library> libraries) {
    Component singlePackageLibraries = new Component(
        libraries: libraries,
        uriToSource: component.uriToSource,
        nameRoot: component.root);
    singlePackageLibraries.setMainMethodAndMode(null, false);

    // Copy all metadata. This should be okay (e.g. not result in a leak)
    // because we serialize now and then (implicitly) throw this component away.
    singlePackageLibraries.metadata.addAll(component.metadata);

    ByteSink byteSink = new ByteSink();
    final BinaryPrinter printer = new BinaryPrinter(byteSink);
    printer.writeComponentFile(singlePackageLibraries);
    return byteSink.builder.takeBytes();
  }

  /// Remove the specified uri from the [uriToGroup] map.
  ///
  /// Also remove all uris in the group the uri belongs to, and add the group to
  /// the worklist.
  void removeUriFromMap(Uri uri, Set<SerializationGroup> removed,
      List<SerializationGroup> workList) {
    SerializationGroup? group = uriToGroup.remove(uri);
    if (group == null) return;
    bool added = removed.add(group);
    assert(added);
    workList.add(group);
    for (Uri groupUri in group.uris) {
      SerializationGroup? sameGroup = uriToGroup.remove(groupUri);
      assert((groupUri == uri && sameGroup == null) ||
          (groupUri != uri && sameGroup != null));
    }
  }
}

// Coverage-ignore(suite): Not run.
class SerializationGroup {
  final Uint8List serializedData;
  final Set<Uri> uris;
  Set<SerializationGroup>? dependencies;
  Set<SerializationGroup>? othersDependingOnMe;

  SerializationGroup(this.serializedData, this.uris);

  /// Register the dependency that this group depends on the [other] one.
  /// The registration is bilateral so that [other] is added as a dependency for
  /// this, and this is added as a "others depend on me" for [other].
  void registerDependency(SerializationGroup other) {
    dependencies ??= new Set<SerializationGroup>.identity();
    if (dependencies!.add(other)) {
      other.othersDependingOnMe ??= new Set<SerializationGroup>.identity();
      other.othersDependingOnMe!.add(this);
    }
  }
}
