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

import 'package:compiler/src/serialization/serialization.dart';

/// Interface for data that may be deserialized lazily.
///
/// This interface should be used to wrap data objects that aren't needed in
/// later phases of the compiler. Usage of this class should follow a set
/// pattern. Given a class `C` with a field `m0` of type `E` that we wish to
/// make deferrable:
///
/// 1) `m0` should be replaced with an internal field, `_m1`, of type
///  `Deferrable<E>`.
/// 2) An internal constructor should be added to `C` that takes a `d` of type
///  `Deferrable<E>` to initialize `_m1`. This internal constructor should be
///  called from the readFromSource method/factory to create the instance
///  of `C`. `d` should be obtained using [DataSourceReader.readDeferrable].
///  Note: [DataSourceReader.readDeferrable] passes the correct
///  [DataSourceReader] to the reader function so that the [DataSourceReader]
///  does not have to be closed over. If necessary a static tear-off should be
///  used as the argument so a closure isn't created for every read.
/// 3) Any existing constructors of `C` should maintain the same signature
///  and initialize `_m1` passing `m` to [Deferrable.eager] where m is the value
///  previously used to initialize `m0`.
/// 4) If there are external references to `m0` then `C`s interface should be
///  maintained. A getter `m0` should be added: `E get m0 => _m1.loaded()`
/// 5) If all references to `m0` were internal, they can simply be replaced
///  with calls to `_m1.loaded()`.
///
/// Example class before:
///
/// ```
/// class Foo {
///   final Bar bar;
///   final String name;
///
///   Foo(this.bar, this.name);
///
///   factory Foo.readFromSource(DataSourceReader reader) {
///     final bar = Bar.readFromSource(reader);
///     final name = reader.readString();
///     return Foo(bar, name);
///   }
/// }
/// ```
///
/// After:
///
/// ```
/// class Foo {
///   Bar get bar => _bar.loaded();
///   final Deferrable<Bar> _bar;
///
///   String get name => _name.loaded();
///   final Deferrable<String> _name;
///
///   Foo(Bar bar, String name) :
///       _bar = Deferrable.eager(bar), _name = Deferrable.eager(name);
///   Foo._deserialized(this._bar, this._name);
///
///   static String readName(DataSourceReader reader) => reader.readString();
///
///   factory Foo.readFromSource(DataSourceReader reader) {
///     final bar = reader.readDeferrable(Bar.readFromSource);
///     final name = reader.readDeferrable(readName);
///     return Foo._deserialized(bar, name);
///   }
/// }
/// ```
abstract class Deferrable<E> {
  E loaded();

  factory Deferrable.deferred(
    DataSourceReader reader,
    E Function(DataSourceReader source) f,
    int offset, {
    bool cacheData = true,
  }) =>
      cacheData
          ? _DeferredCache(reader, f, offset)
          : _Deferred(reader, f, offset);
  static Deferrable<E> deferredWithArg<E, A>(
    DataSourceReader reader,
    E Function(DataSourceReader source, A arg) f,
    A arg,
    int offset, {
    bool cacheData = true,
  }) =>
      cacheData
          ? _DeferredCacheWithArg(reader, f, arg, offset)
          : _DeferredWithArg(reader, f, arg, offset);
  const factory Deferrable.eager(E data) = _Eager;

  const Deferrable();
}

class _Eager<E> extends Deferrable<E> {
  final E _data;
  @override
  E loaded() => _data;
  const _Eager(this._data);
}

class _DeferredWithArg<E, A> extends Deferrable<E> {
  final DataSourceReader _reader;
  final E Function(DataSourceReader source, A arg) _dataLoader;
  final A _arg;
  final int _dataOffset;
  @override
  E loaded() =>
      _reader.readWithOffset(_dataOffset, () => _dataLoader(_reader, _arg));
  _DeferredWithArg(this._reader, this._dataLoader, this._arg, this._dataOffset);
}

class _DeferredCacheWithArg<E, A> extends Deferrable<E> {
  final int _dataOffset;
  // Below fields are nullable so they can be cleared after loading.
  DataSourceReader? _reader;
  E Function(DataSourceReader source, A arg)? _dataLoader;
  A? _arg;
  late final E _data = _loadData();

  @override
  E loaded() => _data;

  E _loadData() {
    final reader = _reader!;
    final dataLoader = _dataLoader!;
    final arg = _arg as A;
    _reader = null;
    _dataLoader = null;
    _arg = null;
    return reader.readWithOffset(_dataOffset, () => dataLoader(reader, arg));
  }

  _DeferredCacheWithArg(
    this._reader,
    this._dataLoader,
    this._arg,
    this._dataOffset,
  );
}

class _Deferred<E> extends Deferrable<E> {
  final DataSourceReader _reader;
  final E Function(DataSourceReader source) _dataLoader;
  final int _dataOffset;
  @override
  E loaded() => _reader.readWithOffset(_dataOffset, () => _dataLoader(_reader));
  _Deferred(this._reader, this._dataLoader, this._dataOffset);
}

class _DeferredCache<E> extends Deferrable<E> {
  final int _dataOffset;
  // Below fields are nullable so they can be cleared after loading.
  DataSourceReader? _reader;
  E Function(DataSourceReader source)? _dataLoader;
  late final E _data = _loadData();

  @override
  E loaded() => _data;

  E _loadData() {
    final reader = _reader!;
    final dataLoader = _dataLoader!;
    _reader = null;
    _dataLoader = null;
    return reader.readWithOffset(_dataOffset, () => dataLoader(reader));
  }

  _DeferredCache(this._reader, this._dataLoader, this._dataOffset);
}

/// Implementation of [Map] in which each value of type [V] is internally
/// [Deferrable].
///
/// This map should be used when values of type [V] are expensive to
/// deserialize. This abstracts away the laziness allowing the deferred map to
/// be used as if the values were not deferred.
///
/// The provided map can have a mix of eager and lazy [Deferrable]s if
/// there are a mix of expensive and cheap values.
class DeferrableValueMap<K, V> with MapMixin<K, V> {
  DeferrableValueMap(this._map);
  final Map<K, Deferrable<V>> _map;
  @override
  V? operator [](Object? key) {
    return _map[key]?.loaded();
  }

  @override
  void operator []=(K key, V value) {
    _map[key] = Deferrable.eager(value);
  }

  @override
  void clear() {
    _map.clear();
  }

  @override
  Iterable<K> get keys => _map.keys;

  @override
  V? remove(Object? key) {
    return _map.remove(key)?.loaded();
  }

  @override
  V putIfAbsent(K key, V Function() ifAbsent) {
    return _map.putIfAbsent(key, () => Deferrable.eager(ifAbsent())).loaded();
  }
}
