// 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:expect/expect.dart';
import "package:async_helper/async_helper.dart";
import 'type_test_helper.dart';
import 'package:compiler/src/dart_types.dart';
import "package:compiler/src/elements/elements.dart"
       show Element, ClassElement;

void main() {
  testMixinSupertypes();
  testNonTrivialSubstitutions();
}

void testMixinSupertypes() {
  asyncTest(() => 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>;
      """, expectNoWarningsOrErrors: true).then((env) {

    ClassElement Object = env.getElement('Object');
    ClassElement S = env.getElement('S');
    ClassElement M1 = env.getElement('M1');
    ClassElement M2 = env.getElement('M2');
    ClassElement M3 = env.getElement('M3');
    ClassElement C1 = env.getElement('C1');
    ClassElement C2 = env.getElement('C2');

    ClassElement C1_S_M1_M2_M3 = C1.superclass;
    ClassElement C1_S_M1_M2 = C1_S_M1_M2_M3.superclass;
    ClassElement C1_S_M1 = C1_S_M1_M2.superclass;

    ClassElement C2_S_M1_M2 = C2.superclass;
    ClassElement C2_S_M1 = C2_S_M1_M2.superclass;

    void testSupertypes(ClassElement element) {
      if (element != Object) {
        Expect.isTrue(element.typeVariables.length == 1);
        Expect.equals(element,
                      element.typeVariables.first.element.enclosingElement);
      }
      for (InterfaceType supertype in element.allSupertypesAndSelf.types) {
        if (!supertype.typeArguments.isEmpty) {
          Expect.listEquals(element.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);
  }));
}

void testNonTrivialSubstitutions() {
  asyncTest(() => 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, _>>;
      """, expectNoWarningsOrErrors: true).then((env) {
    DartType _dynamic = env['dynamic'];
    DartType _ = env['_'];

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

    ClassElement C1_A_B = C1.superclass;
    ClassElement D1_A_B = D1.superclass;
    ClassElement E1_A_B = E1.superclass;
    ClassElement F1_A_B = F1.superclass;

    void testSupertypes(ClassElement element,
                        Map<ClassElement, List<DartType>> typeArguments) {
      if (element != Object) {
        Expect.isTrue(element.typeVariables.length == 1);
        Expect.equals(element,
                      element.typeVariables.first.element.enclosingElement);
      }
      for (InterfaceType supertype in element.allSupertypesAndSelf.types) {
        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(element.typeVariables, supertype.typeArguments,
              "Type argument mismatch on supertype $supertype of $element.");
        } else {
          Expect.equals(Object, supertype.element);
        }
      }
    }

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

    DartType D1_T = D1.typeVariables.first;
    testSupertypes(D1, {A: [D1_T], B: [D1_T, instantiate(A, [D1_T])]});
    DartType D1_superclass_T = D1.superclass.typeVariables.first;
    testSupertypes(D1.superclass,
        {A: [D1_superclass_T],
         B: [D1_superclass_T, instantiate(A, [D1_superclass_T])]});
    DartType D2_T = D2.typeVariables.first;
    testSupertypes(D2, {A: [D2_T], B: [D2_T, instantiate(A, [D2_T])]});

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

    DartType F1_T = F1.typeVariables.first;
    testSupertypes(F1, {A: [_], B: [_, instantiate(B, [F1_T, _])]});
    DartType F1_superclass_T = F1.superclass.typeVariables.first;
    testSupertypes(F1.superclass, {A: [_], B: [_, instantiate(B, [F1_superclass_T, _])]});
    DartType F2_T = F2.typeVariables.first;
    testSupertypes(F2, {A: [_], B: [_, instantiate(B, [F2_T, _])]});
  }));
}
