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

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

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

  // 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 <TypeUse>[];

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

  bool get isEmpty => true;

  void apply(WorldImpactVisitor visitor) {
    staticUses.forEach(visitor.visitStaticUse);
    dynamicUses.forEach(visitor.visitDynamicUse);
    typeUses.forEach(visitor.visitTypeUse);
    constantUses.forEach(visitor.visitConstantUse);
  }

  String toString() => dump(this);

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

  static void printOn(StringBuffer sb, WorldImpact worldImpact) {
    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 {
  void registerDynamicUse(DynamicUse dynamicUse);
  void registerTypeUse(TypeUse typeUse);
  void registerStaticUse(StaticUse staticUse);
  void registerConstantUse(ConstantUse constantUse);
}

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

  @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);
  }

  void registerDynamicUse(DynamicUse dynamicUse) {
    assert(dynamicUse != null);
    if (_dynamicUses == null) {
      _dynamicUses = new Setlet<DynamicUse>();
    }
    _dynamicUses.add(dynamicUse);
  }

  Iterable<DynamicUse> get dynamicUses {
    return _dynamicUses != null ? _dynamicUses : const <DynamicUse>[];
  }

  void registerTypeUse(TypeUse typeUse) {
    assert(typeUse != null);
    if (_typeUses == null) {
      _typeUses = new Setlet<TypeUse>();
    }
    _typeUses.add(typeUse);
  }

  Iterable<TypeUse> get typeUses {
    return _typeUses != null ? _typeUses : const <TypeUse>[];
  }

  void registerStaticUse(StaticUse staticUse) {
    assert(staticUse != null);
    if (_staticUses == null) {
      _staticUses = new Setlet<StaticUse>();
    }
    _staticUses.add(staticUse);
  }

  Iterable<StaticUse> get staticUses {
    return _staticUses != null ? _staticUses : const <StaticUse>[];
  }

  void registerConstantUse(ConstantUse constantUse) {
    assert(constantUse != null);
    if (_constantUses == null) {
      _constantUses = new Setlet<ConstantUse>();
    }
    _constantUses.add(constantUse);
  }

  Iterable<ConstantUse> get constantUses {
    return _constantUses != null ? _constantUses : const <ConstantUse>[];
  }
}

/// [WorldImpactBuilder] that can create and collect a sequence of
/// [WorldImpact]s.
class StagedWorldImpactBuilder implements WorldImpactBuilder {
  final bool collectImpacts;
  WorldImpactBuilderImpl _currentBuilder;
  List<WorldImpactBuilderImpl> _builders = <WorldImpactBuilderImpl>[];

  StagedWorldImpactBuilder({this.collectImpacts: false});

  void _ensureBuilder() {
    if (_currentBuilder == null) {
      _currentBuilder = new WorldImpactBuilderImpl();
      if (collectImpacts) {
        _builders.add(_currentBuilder);
      }
    }
  }

  @override
  void registerTypeUse(TypeUse typeUse) {
    _ensureBuilder();
    _currentBuilder.registerTypeUse(typeUse);
  }

  @override
  void registerDynamicUse(DynamicUse dynamicUse) {
    _ensureBuilder();
    _currentBuilder.registerDynamicUse(dynamicUse);
  }

  @override
  void registerStaticUse(StaticUse staticUse) {
    _ensureBuilder();
    _currentBuilder.registerStaticUse(staticUse);
  }

  @override
  void registerConstantUse(ConstantUse constantUse) {
    _ensureBuilder();
    _currentBuilder.registerConstantUse(constantUse);
  }

  /// Returns the [WorldImpact] built so far with this builder. The builder
  /// is reset, and if [collectImpacts] is `true` the impact is cached for
  /// [worldImpacts].
  WorldImpact flush() {
    if (_currentBuilder == null) return const WorldImpact();
    WorldImpact worldImpact = _currentBuilder;
    _currentBuilder = null;
    return worldImpact;
  }

  /// If [collectImpacts] is `true` this returns all [WorldImpact]s built with
  /// this builder.
  Iterable<WorldImpact> get worldImpacts => _builders;
}

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

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

  TransformedWorldImpact(this.worldImpact);

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

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

  void registerDynamicUse(DynamicUse dynamicUse) {
    if (_dynamicUses == null) {
      _dynamicUses = new Setlet<DynamicUse>();
      _dynamicUses.addAll(worldImpact.dynamicUses);
    }
    _dynamicUses.add(dynamicUse);
  }

  void registerTypeUse(TypeUse typeUse) {
    if (_typeUses == null) {
      _typeUses = new Setlet<TypeUse>();
      _typeUses.addAll(worldImpact.typeUses);
    }
    _typeUses.add(typeUse);
  }

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

  void registerStaticUse(StaticUse staticUse) {
    if (_staticUses == null) {
      _staticUses = new Setlet<StaticUse>();
      _staticUses.addAll(worldImpact.staticUses);
    }
    _staticUses.add(staticUse);
  }

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

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

  void registerConstantUse(ConstantUse constantUse) {
    if (_constantUses == null) {
      _constantUses = new Setlet<ConstantUse>();
      _constantUses.addAll(worldImpact.constantUses);
    }
    _constantUses.add(constantUse);
  }

  void apply(WorldImpactVisitor visitor) {
    staticUses.forEach(visitor.visitStaticUse);
    dynamicUses.forEach(visitor.visitDynamicUse);
    typeUses.forEach(visitor.visitTypeUse);
    constantUses.forEach(visitor.visitConstantUse);
  }

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

/// Constant used to denote a specific use of a [WorldImpact].
class ImpactUseCase {
  final String name;

  const ImpactUseCase(this.name);

  String toString() => 'ImpactUseCase($name)';
}

/// Strategy used for processing [WorldImpact] object in various use cases.
class ImpactStrategy {
  const ImpactStrategy();

  /// Applies [impact] to [visitor] for the [impactUseCase] of [impactSource].
  void visitImpact(var impactSource, WorldImpact impact,
      WorldImpactVisitor visitor, ImpactUseCase impactUseCase) {
    // Apply unconditionally.
    impact.apply(visitor);
  }

  /// Notifies the strategy that no more impacts of [impactUseCase] will be
  /// applied.
  void onImpactUsed(ImpactUseCase impactUseCase) {
    // Do nothing.
  }
}

/// Visitor used to process the uses of a [WorldImpact].
abstract class WorldImpactVisitor {
  void visitStaticUse(StaticUse staticUse);
  void visitDynamicUse(DynamicUse dynamicUse);
  void visitTypeUse(TypeUse typeUse);
  void visitConstantUse(ConstantUse typeUse);
}

// TODO(johnniwinther): Remove these when we get anonymous local classes.
typedef void VisitUse<U>(U use);

class WorldImpactVisitorImpl implements WorldImpactVisitor {
  final VisitUse<StaticUse> _visitStaticUse;
  final VisitUse<DynamicUse> _visitDynamicUse;
  final VisitUse<TypeUse> _visitTypeUse;
  final VisitUse<ConstantUse> _visitConstantUse;

  WorldImpactVisitorImpl(
      {VisitUse<StaticUse> visitStaticUse,
      VisitUse<DynamicUse> visitDynamicUse,
      VisitUse<TypeUse> visitTypeUse,
      VisitUse<ConstantUse> visitConstantUse})
      : _visitStaticUse = visitStaticUse,
        _visitDynamicUse = visitDynamicUse,
        _visitTypeUse = visitTypeUse,
        _visitConstantUse = visitConstantUse;

  @override
  void visitStaticUse(StaticUse use) {
    if (_visitStaticUse != null) {
      _visitStaticUse(use);
    }
  }

  @override
  void visitDynamicUse(DynamicUse use) {
    if (_visitDynamicUse != null) {
      _visitDynamicUse(use);
    }
  }

  @override
  void visitTypeUse(TypeUse use) {
    if (_visitTypeUse != null) {
      _visitTypeUse(use);
    }
  }

  @override
  void visitConstantUse(ConstantUse use) {
    if (_visitConstantUse != null) {
      _visitConstantUse(use);
    }
  }
}
