// 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 isEmptyOrNull => forwardTo.isEmptyOrNull;
  bool get isEmpty => forwardTo.isEmpty;
  bool get isNullable => forwardTo.isNullable;
  bool get isNull => forwardTo.isNull;
  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.isEmptyOrNull) {
      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";
}
