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

import 'package:kernel/kernel.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
import 'package:test/test.dart';
import 'class_hierarchy_basic.dart';
import 'dart:io';
import 'dart:math';
import 'self_check_util.dart';

main(List<String> args) {
  runSelfCheck(args, (String filename) {
    testClassHierarchyOnComponent(loadComponentFromBinary(filename));
  });
}

void testClassHierarchyOnComponent(Component component, {bool verbose: false}) {
  BasicClassHierarchy basic = new BasicClassHierarchy(component);
  CoreTypes coreTypes = new CoreTypes(component);
  ClosedWorldClassHierarchy classHierarchy =
      new ClassHierarchy(component, coreTypes);
  int total = classHierarchy.numberOfClasses;
  int progress = 0;
  for (var class1 in classHierarchy.classes) {
    for (var class2 in classHierarchy.classes) {
      bool isSubclass = classHierarchy.isSubclassOf(class1, class2);
      bool isSubtype = classHierarchy.isSubtypeOf(class1, class2);
      var asInstance = classHierarchy.getClassAsInstanceOf(class1, class2);
      if (isSubclass != basic.isSubclassOf(class1, class2)) {
        fail('isSubclassOf(${class1.name}, ${class2.name}) returned '
            '$isSubclass but should be ${!isSubclass}');
      }
      if (isSubtype != basic.isSubtypeOf(class1, class2)) {
        fail('isSubtypeOf(${class1.name}, ${class2.name}) returned '
            '$isSubtype but should be ${!isSubtype}');
      }
      if (asInstance != basic.getClassAsInstanceOf(class1, class2)) {
        fail('asInstanceOf(${class1.name}, ${class2.name}) returned '
            '$asInstance but should be '
            '${basic.getClassAsInstanceOf(class1, class2)}');
      }
    }
    ++progress;
    if (verbose) {
      stdout.write('\rSubclass queries ${100 * progress ~/ total}%');
    }
  }
  Set<Name> names = new Set<Name>();
  for (var classNode in classHierarchy.classes) {
    for (var member in classNode.members) {
      names.add(member.name);
    }
  }
  List<Name> nameList = names.toList();
  progress = 0;
  for (var classNode in classHierarchy.classes) {
    Iterable<Name> candidateNames = <Iterable<Name>>[
      basic.gettersAndCalls[classNode].keys,
      basic.setters[classNode].keys,
      pickRandom(nameList, 100)
    ].expand((x) => x);
    for (Name name in candidateNames) {
      Member expectedGetter =
          basic.getDispatchTarget(classNode, name, setter: false);
      Member expectedSetter =
          basic.getDispatchTarget(classNode, name, setter: true);
      Member actualGetter =
          classHierarchy.getDispatchTarget(classNode, name, setter: false);
      Member actualSetter =
          classHierarchy.getDispatchTarget(classNode, name, setter: true);
      if (actualGetter != expectedGetter) {
        fail('lookupGetter($classNode, $name) returned '
            '$actualGetter but should be $expectedGetter');
      }
      if (actualSetter != expectedSetter) {
        fail('lookupSetter($classNode, $name) returned '
            '$actualSetter but should be $expectedSetter');
      }
    }
    ++progress;
    if (verbose) {
      stdout.write('\rDispatch queries ${100 * progress ~/ total}%');
    }
  }
  progress = 0;
  for (var classNode in classHierarchy.classes) {
    Iterable<Name> candidateNames = [
      basic.interfaceGettersAndCalls[classNode].keys,
      basic.interfaceSetters[classNode].keys,
      pickRandom(nameList, 100)
    ].expand((x) => x);
    for (Name name in candidateNames) {
      Member expectedGetter =
          basic.getInterfaceMember(classNode, name, setter: false);
      Member expectedSetter =
          basic.getInterfaceMember(classNode, name, setter: true);
      Member actualGetter =
          classHierarchy.getInterfaceMember(classNode, name, setter: false);
      Member actualSetter =
          classHierarchy.getInterfaceMember(classNode, name, setter: true);
      if (actualGetter != expectedGetter) {
        fail('getInterfaceMember($classNode, $name) returned '
            '$actualGetter but should be $expectedGetter');
      }
      if (actualSetter != expectedSetter) {
        fail('getInterfaceMember($classNode, $name, setter: true) '
            'returned $actualSetter but should be $expectedSetter');
      }
    }
    ++progress;
    if (verbose) {
      stdout.write('\rInterface queries ${100 * progress ~/ total}%');
    }
  }
  for (var classNode in classHierarchy.classes) {
    String getHash(member, superMember, setter) {
      String eq = setter ? '=' : '';
      return '$member$eq overrides $superMember$eq';
    }

    Set<String> expectedOverrides = new Set<String>();
    basic.forEachOverridePair(classNode, (member, superMember, setter) {
      expectedOverrides.add(getHash(member, superMember, setter));
    });
    Set<String> actualOverrides = new Set<String>();
    classHierarchy.forEachOverridePair(classNode,
        (member, superMember, setter) {
      actualOverrides.add(getHash(member, superMember, setter));
    });
    for (var actual in actualOverrides) {
      if (!expectedOverrides.contains(actual)) {
        fail("forEachOverridePair($classNode) should not report that $actual");
      }
    }
    for (var expected in expectedOverrides) {
      if (!actualOverrides.contains(expected)) {
        fail("forEachOverridePair($classNode) did not report that $expected");
      }
    }
  }
  if (verbose) {
    print('\rProgress 100%. Done.');
  }
}

var random = new Random(12345);

List<T> pickRandom<T>(List<T> items, int n) {
  var result = <T>[];
  for (int i = 0; i < n; ++i) {
    result.add(items[random.nextInt(items.length)]);
  }
  return result;
}
