// 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.

// @dart = 2.7

import "native_testing.dart";
import 'dart:_js_helper' show setNativeSubclassDispatchRecord;
import 'dart:_interceptors'
    show findInterceptorForType, findConstructorForNativeSubclassType;

// Test for super access from classes that extend native classes.

@Native("N1")
class N1 {}

@Native("N2")
class N2 extends N1 {
  N2.init();
  String text;
  foo() native;
}

class AA extends N2 {
  AA.init() : super.init();
  String afield;
  afun() => 'afun:$afield';
}

class BB extends AA {
  BB.init() : super.init();

  get text => super.text;
  set text(value) => super.text = value;
  foo() => super.foo();

  get afield => super.afield;
  set afield(value) => super.afield = value;
  afun() => super.afun();
}

BB makeBB() native;

@Creates('=Object')
getBBPrototype() native;

void setup() {
  JS('', r"""
(function(){
  function N2() {}
  N2.prototype.foo = function() { return "foo:" + this.text; };
  function BB() {}
  BB.prototype.__proto__ = N2.prototype;
  makeBB = function(){return new BB()};

  getBBPrototype = function(){return BB.prototype;};
})()""");
}

testSuperOnNative() {
  BB b1 = makeBB();
  BB b2 = makeBB();

  var constructor = findConstructorForNativeSubclassType(BB, 'init');
  Expect.isNotNull(constructor);
  JS('', '#(#)', constructor, b1);
  JS('', '#(#)', constructor, b2);

  b1.text = confuse('one');
  b2.text = confuse('two');

  print('b1.text ${confuse(b1).text}');
  print('b2.text ${confuse(b2).text}');

  print('b1.foo() ${confuse(b1).foo()}');
  print('b2.foo() ${confuse(b2).foo()}');

  Expect.equals('one', b1.text);
  Expect.equals('two', b2.text);

  Expect.equals('foo:one', b1.foo());
  Expect.equals('foo:two', b2.foo());

  confuse(b1).text = confuse('three');
  confuse(b2).text = confuse('four');

  Expect.equals('three', confuse(b1).text);
  Expect.equals('four', confuse(b2).text);

  Expect.equals('foo:three', confuse(b1).foo());
  Expect.equals('foo:four', confuse(b2).foo());
}

testSuperOnSubclassOfNative() {
  BB b1 = makeBB();
  BB b2 = makeBB();

  var constructor = findConstructorForNativeSubclassType(BB, 'init');
  Expect.isNotNull(constructor);
  JS('', '#(#)', constructor, b1);
  JS('', '#(#)', constructor, b2);

  b1.afield = confuse('one');
  b2.afield = confuse('two');

  print('b1.afield ${confuse(b1).afield}');
  print('b2.afield ${confuse(b2).afield}');

  print('b1.afun() ${confuse(b1).afun()}');
  print('b2.afun() ${confuse(b2).afun()}');

  Expect.equals('one', b1.afield);
  Expect.equals('two', b2.afield);

  Expect.equals('afun:one', b1.afun());
  Expect.equals('afun:two', b2.afun());

  confuse(b1).afield = confuse('three');
  confuse(b2).afield = confuse('four');

  Expect.equals('three', confuse(b1).afield);
  Expect.equals('four', confuse(b2).afield);

  Expect.equals('afun:three', confuse(b1).afun());
  Expect.equals('afun:four', confuse(b2).afun());
}

main() {
  nativeTesting();
  setup();

  setNativeSubclassDispatchRecord(getBBPrototype(), findInterceptorForType(BB));

  testSuperOnNative();
  testSuperOnSubclassOfNative();
}
