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