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

// Tests basic classes and methods.
class ClassTest {
  ClassTest() {}

  static testMain() {
    var test = new ClassTest();
    test.testSuperCalls();
    test.testVirtualCalls();
    test.testStaticCalls();
    test.testInheritedField();
    test.testMemberRefInClosure();
    test.testFactory();
    test.testNamedConstructors();
    test.testDefaultImplementation();
    test.testFunctionParameter((int a) { return a;});
  }

  testFunctionParameter(int func(int a)) {
    Expect.equals(1, func(1));
  }

  testSuperCalls() {
    var sub = new Sub();
    Expect.equals(43, sub.methodX());
    Expect.equals(84, sub.methodK());
  }

  testVirtualCalls() {
    var sub = new Sub();
    Expect.equals(41, sub.method2());
    Expect.equals(41, sub.method3());
  }

  testStaticCalls() {
    var sub = new Sub();
    Expect.equals(-42, Sub.method4());
    Expect.equals(-41, sub.method5());
  }

  testInheritedField() {
    var sub  = new Sub();
    Expect.equals(42, sub.method6());
  }

  testMemberRefInClosure() {
    var sub = new Sub();
    Expect.equals(1, sub.closureRef());
    Expect.equals(2, sub.closureRef());
    // Make sure it is actually on the object, not the global 'this'.
    sub = new Sub();
    Expect.equals(1, sub.closureRef());
    Expect.equals(2, sub.closureRef());
  }

  testFactory() {
    var sup = new Sup.named();
    Expect.equals(43, sup.methodX());
    Expect.equals(84, sup.methodK());
  }

  testNamedConstructors() {
    var sup = new Sup.fromInt(4);
    Expect.equals(4, sup.methodX());
    Expect.equals(0, sup.methodK());
  }

  testDefaultImplementation() {
    var x = new Inter(4);
    Expect.equals(4, x.methodX());
    Expect.equals(8, x.methodK());

    x = new Inter.fromInt(4);
    Expect.equals(4, x.methodX());
    Expect.equals(0, x.methodK());

    x = new Inter.named();
    Expect.equals(43, x.methodX());
    Expect.equals(84, x.methodK());

    x = new Inter.factory();
    Expect.equals(43, x.methodX());
    Expect.equals(84, x.methodK());
  }
}

abstract class Inter {
  factory Inter.named() = Sup.named;
  factory Inter.fromInt(int x) = Sup.fromInt;
  factory Inter(int x) = Sup;
  factory Inter.factory() = Sup.factory;
  int methodX();
  int methodK();
  int x_;
}

class Sup implements Inter {
  int x_;
  int k_;

  factory Sup.named() {
    return new Sub();
  }

  factory Sup.factory() {
    return new Sub();
  }

  Sup.fromInt(int x) {
    x_ = x;
    k_ = 0;
  }

  int methodX() {
    return x_;
  }

  int methodK() {
    return k_;
  }

  Sup(int x) : this.x_ = x {
    k_ = x * 2;
  }

  int method2() {
    return x_ - 1;
  }
}

class Sub extends Sup {
  int y_;

  // Override
  int methodX() {
    return super.methodX() + 1;
  }

  int method3() {
    return method2();
  }

  static int method4() {
    return -42;
  }

  int method5() {
    return method4() + 1;
  }

  int method6() {
    return x_ + y_;
  }

  int closureRef() {
    var f = () {y_ += 1; return y_;};
    return f();
  }

  Sub() : super(42) {
    y_ = 0;
  }
}

main() {
  ClassTest.testMain();
}
