// 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();
  }
}
