// Copyright (c) 2024, 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';

import 'package:kernel/ast.dart';
import 'package:kernel/binary/ast_from_binary.dart';

/// Helper class for continuously loading kernel dill files that consists of
/// sub components as when serialized via the incremental serializer.
///
/// For instance the frontend-server serializes with the incremental serializer
/// which works by outputting previously serialized component bytes, i.e. a
/// single dill actually contains several components, and many of these
/// components will byte-for-byte be the same between compiles.
///
/// This helper class will do checksums of the bytes of each sub component (and
/// byte-for-byte check on match), to avoid loading previously loaded data.
///
/// In some cases we might even have access to identical data between loads
/// which allows us to skip creating a checksum and comparing bytes, but instead
/// rely on the identity of the list.
class MultiBinaryLoader {
  /// Map from the adler32 checksum to the (possibly multiple) previously loaded
  /// data.
  final Map<int, List<_LoadedData>> _adlerToData = {};

  /// Identity-map from the original list to the loaded equivalent.
  final Map<Uint8List, _LoadedData> _identityHashToData = new Map.identity();

  /// The canonical name root *everything* is loaded in to.
  final CanonicalName _canonicalNameRoot = new CanonicalName.root();

  /// Check if the bytes match, i.e. if the bytes in [data] from [from] to [to]
  /// matches the bytes in the [candidate].
  bool _checkCandidate(
    Uint8List data,
    int from,
    int to,
    _LoadedData candidate,
  ) {
    int length = to - from;
    if (length != candidate.data.length) return false;
    for (int i = 0, j = from; i < length; i++, j++) {
      if (data[j] != candidate.data[i]) {
        return false;
      }
    }
    return true;
  }

  /// Load the data provided in [allData] into a component.
  ///
  /// [allData] is a list to allow loading several chunks, e.g. loading the
  /// platform together with a serialized component without the platform.
  /// [alternativeData] can optionally give an alternative version of some data
  /// range. This would possibly allow for skipping the creation of a checksum.
  Component load(
    List<Uint8List> allData,
    Uint8List? Function(Uint8List data, int from, int to)? alternativeData,
  ) {
    List<_LoadedData> subComponents = [];

    for (Uint8List orgData in allData) {
      for (SubComponentView subView in BinaryBuilder.index(orgData)) {
        int from = subView.componentStartOffset;
        int to = subView.componentStartOffset + subView.componentFileSize;
        if (from == 0 && to == orgData.length) {
          _LoadedData? found = _identityHashToData[orgData];
          if (found != null) {
            subComponents.add(found);
            continue;
          }
        }
        Uint8List data = orgData;
        if (alternativeData != null) {
          Uint8List? alternative = alternativeData(data, from, to);
          if (alternative != null) {
            data = alternative;
            from = 0;
            to = alternative.length;
            _LoadedData? found = _identityHashToData[alternative];
            if (found != null) {
              subComponents.add(found);
              continue;
            }
          }
        }

        _LoadedData? found;
        final int checksum = _adler32(data, from, to);
        final List<_LoadedData> lookup = _adlerToData[checksum] ??= [];
        for (_LoadedData candidate in lookup) {
          // Checksum matches --- check the actual bytes.
          if (_checkCandidate(data, from, to, candidate)) {
            found = candidate;
            break;
          }
        }

        if (found == null) {
          // Load and add.
          // The subData is a view, so if we save that we'll make the while file
          // live in memory. We don't want that so we make a "physical" copy.
          Uint8List subData = new Uint8List(to - from);
          subData.setRange(0, subData.length, data, from);
          BinaryBuilder bb = new BinaryBuilder(
            subData,
            disableLazyReading: true,
            useGrowableLists: false,
            alwaysCreateNewNamedNodes: true,
          );
          Component component = new Component(nameRoot: _canonicalNameRoot);
          bb.readComponent(component);

          List<CanonicalName> linkTable = bb.linkTable;
          found = new _LoadedData(subData, component, linkTable);
          lookup.add(found);
        }

        if (from == 0 && to == data.length) {
          _identityHashToData[data] = found;
        }

        // Add data to combined output.
        subComponents.add(found);
      }
    }

    // Create the combined component and link it up.
    Component result = new Component(nameRoot: _canonicalNameRoot);
    for (_LoadedData subComponent in subComponents) {
      // At first none of the canonical names (or, references really) in the
      // requested data should point to anything.
      for (CanonicalName canonicalName in subComponent.linkTable) {
        canonicalName.referenceOrNull?.node = null;
      }

      result.libraries.addAll(subComponent.component.libraries);
      // TODO: Set main method, combine sources etc.
    }

    // Then we relink everything, effectively making canonical names
    // (references) point to the right things iff it's in the data we was asked
    // to load.
    for (Library library in result.libraries) {
      library.parent = result;
      library.relink();
    }

    // We could check all the used canonical names if they're set.
    // TODO: Should this be optional?
    for (_LoadedData subComponent in subComponents) {
      for (CanonicalName canonicalName in subComponent.linkTable) {
        canonicalName.checkThisCanonicalName();
      }
    }

    return result;
  }
}

class _LoadedData {
  final Uint8List data;
  final Component component;
  final List<CanonicalName> linkTable;

  _LoadedData(this.data, this.component, this.linkTable);
}

/// Calculate the "Adler-32" checksum.
///
/// See https://en.wikipedia.org/wiki/Adler-32 for details.
int _adler32(Uint8List data, int from, int to) {
  int a = 1;
  int b = 0;
  for (int i = from; i < to; i++) {
    a += data[i];
    b += a;

    if (i & 255 == 255) {
      a %= 65521;
      b %= 65521;
    }
  }
  a %= 65521;
  b %= 65521;
  return (b << 16) | a;
}
