// 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';

void 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) as ClosedWorldClassHierarchy;
  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;
}
