// 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 '../dart_types.dart' show
    DartType,
    InterfaceType;
import '../elements/elements.dart' show
    Element,
    LocalFunctionElement,
    MethodElement;
import '../util/util.dart' show
    Setlet;

import 'use.dart' show
    DynamicUse,
    StaticUse,
    TypeUse;

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

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

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

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

  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>[];
  }
}

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

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

  TransformedWorldImpact(this.worldImpact);

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

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

  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 [element].
  void visitImpact(Element element,
                   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);
}

// 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;

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

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

