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

library mixin_typevariable_test;

import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/elements/types.dart';
import 'package:expect/expect.dart';
import '../helpers/type_test_helper.dart';

void main() {
  asyncTest(() async {
    await testMixinSupertypes();
    await testNonTrivialSubstitutions();
  });
}

testMixinSupertypes() async {
  var env = await TypeEnvironment.create(r"""
      class S<S_T> {}
      class M1<M1_T> {}
      class M2<M2_T> {}
      class M3<M3_T> {}

      class C1<C1_T> extends S<C1_T> with M1<C1_T>, M2<C1_T>, M3<C1_T> {}
      class C2<C2_T> = S<C2_T> with M1<C2_T>, M2<C2_T>, M3<C2_T>;

      main() {
        new C1();
        new C2();
      }
      """, expectNoWarningsOrErrors: true);
  ClassEntity Object = env.getElement('Object');
  ClassEntity S = env.getClass('S');
  ClassEntity M1 = env.getClass('M1');
  ClassEntity M2 = env.getClass('M2');
  ClassEntity C1 = env.getClass('C1');
  ClassEntity C2 = env.getClass('C2');

  ClassEntity C1_S_M1_M2_M3 = env.elementEnvironment.getSuperClass(C1);
  ClassEntity C1_S_M1_M2 = env.elementEnvironment.getSuperClass(C1_S_M1_M2_M3);
  ClassEntity C1_S_M1 = env.elementEnvironment.getSuperClass(C1_S_M1_M2);

  ClassEntity C2_S_M1_M2 = env.elementEnvironment.getSuperClass(C2);
  ClassEntity C2_S_M1 = env.elementEnvironment.getSuperClass(C2_S_M1_M2);

  void testSupertypes(ClassEntity element) {
    List<DartType> typeVariables = const <DartType>[];
    if (element != Object) {
      typeVariables = env.elementEnvironment.getThisType(element).typeArguments;
      Expect.isTrue(typeVariables.length == 1);
      TypeVariableType typeVariable = typeVariables.first;
      Expect.equals(element, typeVariable.element.typeDeclaration);
    }
    env.elementEnvironment.forEachSupertype(element, (InterfaceType supertype) {
      if (!supertype.typeArguments.isEmpty) {
        Expect.listEquals(typeVariables, supertype.typeArguments,
            "Type argument mismatch on supertype $supertype of $element.");
      } else {
        Expect.equals(Object, supertype.element);
      }
    });
  }

  testSupertypes(Object);
  testSupertypes(S);
  testSupertypes(M1);
  testSupertypes(M2);
  testSupertypes(C1_S_M1);
  testSupertypes(C1_S_M1_M2);
  testSupertypes(C1_S_M1_M2_M3);
  testSupertypes(C1);
  testSupertypes(C2_S_M1);
  testSupertypes(C2_S_M1_M2);
  testSupertypes(C2);
}

testNonTrivialSubstitutions() async {
  var env = await TypeEnvironment.create(r"""
      class _ {}
      class A<A_T> {}
      class B<B_T, B_S> {}

      class C1<C1_T> extends A with B {}
      class C2<C2_T> = A with B;

      class D1<D1_T> extends A<D1_T> with B<D1_T, A<D1_T>> {}
      class D2<D2_T> = A<D2_T> with B<D2_T, A<D2_T>>;

      class E1<E1_T> extends A<_> with B<_, A<_>> {}
      class E2<E2_T> = A<_> with B<_, A<_>>;

      class F1<F1_T> extends A<_> with B<_, B<F1_T, _>> {}
      class F2<F2_T> = A<_> with B<_, B<F2_T, _>>;

      main() {
        new C1();
        new C2();
        new D1();
        new D2();
        new E1();
        new E2();
        new F1();
        new F2();
      }
      """, expectNoWarningsOrErrors: true);
  DartType _dynamic = env['dynamic'];
  DartType _ = env['_'];

  ClassEntity Object = env.getElement('Object');
  ClassEntity A = env.getClass('A');
  ClassEntity B = env.getClass('B');
  ClassEntity C1 = env.getClass('C1');
  ClassEntity C2 = env.getClass('C2');
  ClassEntity D1 = env.getClass('D1');
  ClassEntity D2 = env.getClass('D2');
  ClassEntity E1 = env.getClass('E1');
  ClassEntity E2 = env.getClass('E2');
  ClassEntity F1 = env.getClass('F1');
  ClassEntity F2 = env.getClass('F2');

  void testSupertypes(
      ClassEntity element, Map<ClassEntity, List<DartType>> typeArguments) {
    List<DartType> typeVariables = const <DartType>[];
    if (element != Object) {
      typeVariables = env.elementEnvironment.getThisType(element).typeArguments;
      if (env.elementEnvironment.isUnnamedMixinApplication(element)) {
        // Kernel doesn't add type variables to unnamed mixin applications when
        // these aren't need for its supertypes.
        Expect.isTrue(typeVariables.length <= 1);
      } else {
        Expect.isTrue(typeVariables.length == 1);
      }
      if (typeVariables.isNotEmpty) {
        TypeVariableType typeVariable = typeVariables.first;
        Expect.equals(element, typeVariable.element.typeDeclaration);
      }
    }
    env.elementEnvironment.forEachSupertype(element, (InterfaceType supertype) {
      if (typeArguments.containsKey(supertype.element)) {
        Expect.listEquals(
            typeArguments[supertype.element],
            supertype.typeArguments,
            "Type argument mismatch on supertype $supertype of $element.");
      } else if (!supertype.typeArguments.isEmpty) {
        Expect.listEquals(typeVariables, supertype.typeArguments,
            "Type argument mismatch on supertype $supertype of $element.");
      } else if (env.elementEnvironment
          .isUnnamedMixinApplication(supertype.element)) {
        // Kernel doesn't add type variables to unnamed mixin applications when
        // these aren't need for its supertypes.
        Expect.isTrue(supertype.typeArguments.isEmpty,
            "Type argument mismatch on supertype $supertype of $element.");
      } else {
        Expect.equals(Object, supertype.element,
            "Type argument mismatch on supertype $supertype of $element.");
      }
    });
  }

  testSupertypes(C1, {
    A: [_dynamic],
    B: [_dynamic, _dynamic]
  });
  testSupertypes(env.elementEnvironment.getSuperClass(C1), {
    A: [_dynamic],
    B: [_dynamic, _dynamic]
  });
  testSupertypes(C2, {
    A: [_dynamic],
    B: [_dynamic, _dynamic]
  });

  DartType D1_T = env.elementEnvironment.getThisType(D1).typeArguments.first;
  testSupertypes(D1, {
    A: [D1_T],
    B: [
      D1_T,
      instantiate(A, [D1_T])
    ]
  });
  DartType D1_superclass_T = env.elementEnvironment
      .getThisType(env.elementEnvironment.getSuperClass(D1))
      .typeArguments
      .first;
  testSupertypes(env.elementEnvironment.getSuperClass(D1), {
    A: [D1_superclass_T],
    B: [
      D1_superclass_T,
      instantiate(A, [D1_superclass_T])
    ]
  });
  DartType D2_T = env.elementEnvironment.getThisType(D2).typeArguments.first;
  testSupertypes(D2, {
    A: [D2_T],
    B: [
      D2_T,
      instantiate(A, [D2_T])
    ]
  });

  testSupertypes(E1, {
    A: [_],
    B: [
      _,
      instantiate(A, [_])
    ]
  });
  testSupertypes(env.elementEnvironment.getSuperClass(E1), {
    A: [_],
    B: [
      _,
      instantiate(A, [_])
    ]
  });
  testSupertypes(E2, {
    A: [_],
    B: [
      _,
      instantiate(A, [_])
    ]
  });

  DartType F1_T = env.elementEnvironment.getThisType(F1).typeArguments.first;
  testSupertypes(F1, {
    A: [_],
    B: [
      _,
      instantiate(B, [F1_T, _])
    ]
  });
  DartType F1_superclass_T = env.elementEnvironment
      .getThisType(env.elementEnvironment.getSuperClass(F1))
      .typeArguments
      .first;
  testSupertypes(env.elementEnvironment.getSuperClass(F1), {
    A: [_],
    B: [
      _,
      instantiate(B, [F1_superclass_T, _])
    ]
  });
  DartType F2_T = env.elementEnvironment.getThisType(F2).typeArguments.first;
  testSupertypes(F2, {
    A: [_],
    B: [
      _,
      instantiate(B, [F2_T, _])
    ]
  });
}
