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

part of types;

/**
 * A type mask that wraps an other one, and delegate all its
 * implementation methods to it.
 */
abstract class ForwardingTypeMask implements TypeMask {

  TypeMask get forwardTo;

  ForwardingTypeMask();

  bool get isEmpty => forwardTo.isEmpty;
  bool get isNullable => forwardTo.isNullable;
  bool get isExact => forwardTo.isExact;

  bool get isUnion => false;
  bool get isContainer => false;
  bool get isMap => false;
  bool get isDictionary => false;
  bool get isValue => false;
  bool get isForwarding => true;

  bool isInMask(TypeMask other, ClassWorld classWorld) {
    return forwardTo.isInMask(other, classWorld);
  }

  bool containsMask(TypeMask other, ClassWorld classWorld) {
    return forwardTo.containsMask(other, classWorld);
  }

  bool containsOnlyInt(ClassWorld classWorld) {
    return forwardTo.containsOnlyInt(classWorld);
  }

  bool containsOnlyDouble(ClassWorld classWorld) {
    return forwardTo.containsOnlyDouble(classWorld);
  }

  bool containsOnlyNum(ClassWorld classWorld) {
    return forwardTo.containsOnlyNum(classWorld);
  }

  bool containsOnlyBool(ClassWorld classWorld) {
    return forwardTo.containsOnlyBool(classWorld);
  }

  bool containsOnlyString(ClassWorld classWorld) {
    return forwardTo.containsOnlyString(classWorld);
  }

  bool containsOnly(ClassElement element) {
    return forwardTo.containsOnly(element);
  }

  bool satisfies(ClassElement cls, ClassWorld classWorld) {
    return forwardTo.satisfies(cls, classWorld);
  }

  bool contains(ClassElement type, ClassWorld classWorld) {
    return forwardTo.contains(type, classWorld);
  }

  bool containsAll(ClassWorld classWorld) {
    return forwardTo.containsAll(classWorld);
  }

  ClassElement singleClass(ClassWorld classWorld) {
    return forwardTo.singleClass(classWorld);
  }

  TypeMask union(other, ClassWorld classWorld) {
    if (this == other) {
      return this;
    } else if (equalsDisregardNull(other)) {
      return other.isNullable ? other : this;
    } else if (other.isEmpty) {
      return other.isNullable ? this.nullable() : this;
    }
    return forwardTo.union(other, classWorld);
  }

  bool isDisjoint(TypeMask other, ClassWorld classWorld) {
    return forwardTo.isDisjoint(other, classWorld);
  }

  TypeMask intersection(TypeMask other, ClassWorld classWorld) {
    return forwardTo.intersection(other, classWorld);
  }

  bool needsNoSuchMethodHandling(Selector selector, ClassWorld classWorld) {
    return forwardTo.needsNoSuchMethodHandling(selector, classWorld);
  }

  bool canHit(Element element, Selector selector, ClassWorld classWorld) {
    return forwardTo.canHit(element, selector, classWorld);
  }

  Element locateSingleElement(Selector selector,
                              TypeMask mask,
                              Compiler compiler) {
    return forwardTo.locateSingleElement(selector, mask, compiler);
  }

  bool equalsDisregardNull(other) {
    if (other is! ForwardingTypeMask) return false;
    if (forwardTo.isNullable) {
      return forwardTo == other.forwardTo.nullable();
    } else {
      return forwardTo == other.forwardTo.nonNullable();
    }
  }

  bool operator==(other) {
    return equalsDisregardNull(other) && isNullable == other.isNullable;
  }

  int get hashCode => throw "Subclass should implement hashCode getter";
}
