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

// @dart = 2.7

import "native_testing.dart";

// Additional Dart code may be 'placed on' hidden native classes.  With
// inheritance, the superclass method must not be reached by a call on the
// subclass.

@Native("A")
class A {
  var _field;

  int get X => _field;
  void set X(int x) {
    _field = x;
  }

  int method(int z) => _field + z;
}

@Native("B")
class B extends A {
  var _field2;

  int get X => _field2;
  void set X(int x) {
    _field2 = x;
  }

  int method(int z) => _field2 + z;
}

A makeA() native;
B makeB() native;

void setup() {
  JS('', r"""
(function(){
  function inherits(child, parent) {
    if (child.prototype.__proto__) {
      child.prototype.__proto__ = parent.prototype;
    } else {
      function tmp() {};
      tmp.prototype = parent.prototype;
      child.prototype = new tmp();
      child.prototype.constructor = child;
    }
  }

  function A(){}
  function B(){}
  inherits(B, A);
  self.makeA = function(){return new A()};
  self.makeB = function(){return new B()};

  self.nativeConstructor(A);
  self.nativeConstructor(B);
})()""");
  applyTestExtensions(['A', 'B']);
}

testBasicA_dynamic() {
  setup(); // Fresh constructors.

  var a = [makeA()][0];

  a.X = 100;
  Expect.equals(100, a._field);
  Expect.equals(100, a.X);
  Expect.equals(150, a.method(50));
}

testBasicA_typed() {
  setup(); // Fresh constructors.

  A a = makeA();

  a.X = 100;
  Expect.equals(100, a._field);
  Expect.equals(100, a.X);
  Expect.equals(150, a.method(50));
}

testBasicB_dynamic() {
  setup(); // Fresh constructors.

  var b = [makeB()][0];

  b._field = 1;
  b.X = 123;
  Expect.equals(1, b._field);
  Expect.equals(123, b._field2);
  Expect.equals(123, b.X);
  Expect.equals(200, b.method(77));
}

testBasicB_typed() {
  setup(); // Fresh constructors.

  B b = makeB();

  b._field = 1;
  b.X = 123;
  Expect.equals(1, b._field);
  Expect.equals(123, b._field2);
  Expect.equals(123, b.X);
  Expect.equals(200, b.method(77));
}

testAB_dynamic() {
  setup(); // Fresh constructors.

  var things = <dynamic>[makeA(), makeB()];
  var a = things[0];
  var b = things[1];

  a.X = 100;
  Expect.equals(100, a._field);
  Expect.equals(100, a.X);
  Expect.equals(150, a.method(50));

  b._field = 1;
  b._field2 = 2;
  b.X = 123;
  Expect.equals(1, b._field);
  Expect.equals(123, b._field2);
  Expect.equals(123, b.X);
  Expect.equals(200, b.method(77));
}

testAB_typed() {
  setup(); // Fresh constructors.

  A a = makeA();
  B b = makeB();

  a.X = 100;
  Expect.equals(100, a._field);
  Expect.equals(100, a.X);
  Expect.equals(150, a.method(50));

  b._field = 1;
  b._field2 = 2;
  b.X = 123;
  Expect.equals(1, b._field);
  Expect.equals(123, b._field2);
  Expect.equals(123, b.X);
  Expect.equals(200, b.method(77));
}

main() {
  nativeTesting();
  testBasicA_dynamic();
  testBasicA_typed();
  testBasicB_dynamic();
  testBasicB_typed();
  testAB_dynamic();
  testAB_typed();
}
