// 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_interfaces.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].
/// 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;
///
///   Foo(this.bar);
///
///   factory Foo.readFromSource(DataSourceReader reader) {
///     return Foo(Bar.readFromSource(reader));
///   }
/// }
///
/// After:
///
/// class Foo {
///   Bar get bar => _bar.loaded();
///   final Deferrable<Bar> _bar;
///
///   Foo(Bar bar) : _bar = Deferrable.eager(bar);
///   Foo._deserialized(this._bar);
///
///   factory Foo.readFromSource(DataSourceReader reader) {
///     return Foo._deserialized(
///         reader.readDeferrable(() => Bar.readFromSource(reader)));
///   }
/// }
abstract class Deferrable<E> {
  E loaded();

  factory Deferrable.deferred(DataSourceReader reader, E f(), int offset,
          {bool cacheData = true}) =>
      cacheData
          ? _DeferredCache(reader, f, offset)
          : _Deferred(reader, f, 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 _Deferred<E> extends Deferrable<E> {
  final DataSourceReader _reader;
  final E Function() _dataLoader;
  final int _dataOffset;
  @override
  E loaded() => _reader.readWithOffset(_dataOffset, _dataLoader);
  _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()? _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);
  }

  _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 ifAbsent()) {
    return _map.putIfAbsent(key, () => Deferrable.eager(ifAbsent())).loaded();
  }
}
