// Copyright (c) 2015, 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.

library dart2js.universe.world_impact;

import '../elements/entities.dart';
import '../util/util.dart' show Setlet;
import 'use.dart';

/// Describes how an element (e.g. a method) impacts the closed-world
/// semantics of a program.
///
/// A [WorldImpact] contains information about how a program element affects our
/// understanding of what's live in a program. For example, it can indicate
/// that a method uses a certain feature, or allocates a specific type.
///
/// The impact object can be computed locally by inspecting just the resolution
/// information of that element alone. The compiler uses [Universe] and
/// [World] to combine the information discovered in the impact objects of
/// all elements reachable in an application.
class WorldImpact {
  const WorldImpact();

  /// [member] may be `null` when the impact is for something that is not a
  /// member, e.g. a constant, or external or native dependencies.
  MemberEntity? get member => null;

  Iterable<DynamicUse> get dynamicUses => const [];

  Iterable<StaticUse> get staticUses => const [];

  // TODO(johnniwinther): Replace this by called constructors with type
  // arguments.
  // TODO(johnniwinther): Collect all checked types for checked mode separately
  // to support serialization.

  Iterable<TypeUse> get typeUses => const [];

  Iterable<ConstantUse> get constantUses => const [];

  void _forEach<U>(
          Iterable<U> uses, void Function(MemberEntity?, U) visitUse) =>
      uses.forEach((use) => visitUse(member, use));

  void forEachDynamicUse(void Function(MemberEntity?, DynamicUse) visitUse) =>
      _forEach(dynamicUses, visitUse);
  void forEachStaticUse(void Function(MemberEntity?, StaticUse) visitUse) =>
      _forEach(staticUses, visitUse);
  void forEachTypeUse(void Function(MemberEntity?, TypeUse) visitUse) =>
      _forEach(typeUses, visitUse);
  void forEachConstantUse(void Function(MemberEntity?, ConstantUse) visitUse) =>
      _forEach(constantUses, visitUse);

  bool get isEmpty => true;

  @override
  String toString() => dump(this);

  static String dump(WorldImpact worldImpact) {
    StringBuffer sb = StringBuffer();
    printOn(sb, worldImpact);
    return sb.toString();
  }

  static void printOn(StringBuffer sb, WorldImpact worldImpact) {
    sb.write('member: ${worldImpact.member}');

    void add(String title, Iterable iterable) {
      if (iterable.isNotEmpty) {
        sb.write('\n $title:');
        iterable.forEach((e) => sb.write('\n  $e'));
      }
    }

    add('dynamic uses', worldImpact.dynamicUses);
    add('static uses', worldImpact.staticUses);
    add('type uses', worldImpact.typeUses);
    add('constant uses', worldImpact.constantUses);
  }
}

abstract class WorldImpactBuilder extends WorldImpact {
  void registerDynamicUse(DynamicUse dynamicUse);
  void registerTypeUse(TypeUse typeUse);
  void registerStaticUse(StaticUse staticUse);
  void registerConstantUse(ConstantUse constantUse);
}

class WorldImpactBuilderImpl extends WorldImpactBuilder {
  /// The [MemberEntity] associated with this set of impacts. Maybe null.
  @override
  final MemberEntity? member;

  // TODO(johnniwinther): Do we benefit from lazy initialization of the
  // [Setlet]s?
  Set<DynamicUse>? _dynamicUses;
  Set<StaticUse>? _staticUses;
  Set<TypeUse>? _typeUses;
  Set<ConstantUse>? _constantUses;

  WorldImpactBuilderImpl([this.member]);

  WorldImpactBuilderImpl.internal(
      this._dynamicUses, this._staticUses, this._typeUses, this._constantUses,
      {this.member});

  @override
  bool get isEmpty =>
      _dynamicUses == null &&
      _staticUses == null &&
      _typeUses == null &&
      _constantUses == null;

  /// Copy uses in [impact] to this impact builder.
  void addImpact(WorldImpact impact) {
    if (impact.isEmpty) return;
    impact.dynamicUses.forEach(registerDynamicUse);
    impact.staticUses.forEach(registerStaticUse);
    impact.typeUses.forEach(registerTypeUse);
    impact.constantUses.forEach(registerConstantUse);
  }

  @override
  void registerDynamicUse(DynamicUse dynamicUse) {
    assert((dynamicUse as dynamic) != null); // TODO(48820): Remove when sound.
    (_dynamicUses ??= Setlet()).add(dynamicUse);
  }

  @override
  Iterable<DynamicUse> get dynamicUses {
    return _dynamicUses ?? const [];
  }

  @override
  void registerTypeUse(TypeUse typeUse) {
    assert((typeUse as dynamic) != null); // TODO(48820): Remove when sound.
    (_typeUses ??= Setlet()).add(typeUse);
  }

  @override
  Iterable<TypeUse> get typeUses {
    return _typeUses ?? const [];
  }

  @override
  void registerStaticUse(StaticUse staticUse) {
    assert((staticUse as dynamic) != null); // TODO(48820): Remove when sound.
    (_staticUses ??= Setlet()).add(staticUse);
  }

  @override
  Iterable<StaticUse> get staticUses {
    return _staticUses ?? const [];
  }

  @override
  void registerConstantUse(ConstantUse constantUse) {
    assert((constantUse as dynamic) != null); // TODO(48820): Remove when sound.
    (_constantUses ??= Setlet()).add(constantUse);
  }

  @override
  Iterable<ConstantUse> get constantUses {
    return _constantUses ?? const [];
  }
}

/// Mutable implementation of [WorldImpact] used to transform
/// [ResolutionImpact] or [CodegenImpact] to [WorldImpact].
class TransformedWorldImpact extends WorldImpactBuilder {
  final WorldImpact worldImpact;

  Setlet<StaticUse>? _staticUses;
  Setlet<TypeUse>? _typeUses;
  Setlet<DynamicUse>? _dynamicUses;
  Setlet<ConstantUse>? _constantUses;

  TransformedWorldImpact(this.worldImpact);

  @override
  MemberEntity? get member => worldImpact.member;

  @override
  bool get isEmpty {
    return worldImpact.isEmpty &&
        _staticUses == null &&
        _typeUses == null &&
        _dynamicUses == null &&
        _constantUses == null;
  }

  @override
  Iterable<DynamicUse> get dynamicUses {
    return _dynamicUses ?? worldImpact.dynamicUses;
  }

  @override
  void registerDynamicUse(DynamicUse dynamicUse) {
    _dynamicUses ??= Setlet.of(worldImpact.dynamicUses);
    _dynamicUses!.add(dynamicUse);
  }

  @override
  void registerTypeUse(TypeUse typeUse) {
    _typeUses ??= Setlet.of(worldImpact.typeUses);
    _typeUses!.add(typeUse);
  }

  @override
  Iterable<TypeUse> get typeUses {
    return _typeUses ?? worldImpact.typeUses;
  }

  @override
  void registerStaticUse(StaticUse staticUse) {
    _staticUses ??= Setlet.of(worldImpact.staticUses);
    _staticUses!.add(staticUse);
  }

  @override
  Iterable<StaticUse> get staticUses {
    return _staticUses ?? worldImpact.staticUses;
  }

  @override
  Iterable<ConstantUse> get constantUses {
    return _constantUses ?? worldImpact.constantUses;
  }

  @override
  void registerConstantUse(ConstantUse constantUse) {
    _constantUses ??= Setlet.of(worldImpact.constantUses);
    _constantUses!.add(constantUse);
  }

  @override
  String toString() {
    StringBuffer sb = StringBuffer();
    sb.write('TransformedWorldImpact($worldImpact)');
    WorldImpact.printOn(sb, this);
    return sb.toString();
  }
}
