// Copyright (c) 2021, 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 'dart:io' show Directory, Platform;
import 'package:_fe_analyzer_shared/src/testing/features.dart';
import 'package:_fe_analyzer_shared/src/testing/id.dart';
import 'package:_fe_analyzer_shared/src/testing/id_testing.dart';
import 'package:front_end/src/testing/id_testing_helper.dart';
import 'package:front_end/src/testing/id_testing_utils.dart';
import 'package:front_end/src/fasta/kernel/class_hierarchy_builder.dart';
import 'package:front_end/src/testing/id_extractor.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/core_types.dart';

Future<void> main(List<String> args) async {
  Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
  await runTests<Features>(dataDir,
      args: args,
      createUriForFileName: createUriForFileName,
      onFailure: onFailure,
      runTest: runTestFor(
          const ClassHierarchyDataComputer(), [cfeNonNullableConfig]));
}

class ClassHierarchyDataComputer extends DataComputer<Features> {
  const ClassHierarchyDataComputer();

  /// Function that computes a data mapping for [library].
  ///
  /// Fills [actualMap] with the data.
  @override
  void computeLibraryData(
      TestConfig config,
      InternalCompilerResult compilerResult,
      Library library,
      Map<Id, ActualData<Features>> actualMap,
      {bool? verbose}) {
    new InheritanceDataExtractor(compilerResult, actualMap)
        .computeForLibrary(library);
  }

  @override
  void computeClassData(
      TestConfig config,
      InternalCompilerResult compilerResult,
      Class cls,
      Map<Id, ActualData<Features>> actualMap,
      {bool? verbose}) {
    new InheritanceDataExtractor(compilerResult, actualMap)
        .computeForClass(cls);
  }

  @override
  bool get supportsErrors => true;

  @override
  Features? computeErrorData(TestConfig config, InternalCompilerResult compiler,
      Id id, List<FormattedMessage> errors) {
    return null; //errorsToText(errors, useCodes: true);
  }

  @override
  DataInterpreter<Features> get dataValidator =>
      const FeaturesDataInterpreter();
}

class Tag {
  static const String superclasses = 'superclasses';
  static const String interfaces = 'interfaces';
  static const String hasNoSuchMethod = 'hasNoSuchMethod';
  static const String abstractMembers = 'abstractMembers';
  static const String classBuilder = 'classBuilder';
  static const String isSourceDeclaration = 'isSourceDeclaration';
  static const String isSynthesized = 'isSynthesized';
  static const String member = 'member';
  static const String maxInheritancePath = 'maxInheritancePath';
  static const String declaredOverrides = 'declared-overrides';
  static const String mixinApplicationOverrides = 'mixin-overrides';
  static const String inheritedImplements = 'inherited-implements';
  static const String abstractForwardingStub = 'abstractForwardingStub';
  static const String concreteForwardingStub = 'concreteForwardingStub';
  static const String memberSignature = 'memberSignature';
  static const String abstractMixinStub = 'abstractMixinStub';
  static const String concreteMixinStub = 'concreteMixinStub';
  static const String declarations = 'declarations';
  static const String stubTarget = 'stubTarget';
  static const String type = 'type';
  static const String covariance = 'covariance';
}

class InheritanceDataExtractor extends CfeDataExtractor<Features> {
  final InternalCompilerResult _compilerResult;

  InheritanceDataExtractor(
      this._compilerResult, Map<Id, ActualData<Features>> actualMap)
      : super(_compilerResult, actualMap);

  CoreTypes get _coreTypes => _compilerResult.coreTypes!;

  ClassHierarchyBuilder get _classHierarchyBuilder =>
      _compilerResult.kernelTargetForTesting!.loader.builderHierarchy;

  @override
  void computeForClass(Class node) {
    super.computeForClass(node);
    ClassHierarchyNode classHierarchyNode =
        _classHierarchyBuilder.getNodeFromClass(node);
    ClassHierarchyNodeDataForTesting data = classHierarchyNode.dataForTesting!;
    void addMember(ClassMember classMember,
        {required bool isSetter, required bool isClassMember}) {
      Member member = classMember.getMember(_classHierarchyBuilder);
      Member memberOrigin = member.memberSignatureOrigin ?? member;
      if (memberOrigin.enclosingClass == _coreTypes.objectClass) {
        return;
      }
      Features features = new Features();

      String memberName = classMemberName(classMember);
      memberName += isClassMember ? '#cls' : '#int';
      MemberId id = new MemberId.internal(memberName, className: node.name);

      TreeNode nodeWithOffset;
      if (member.enclosingClass == node) {
        nodeWithOffset = computeTreeNodeWithOffset(member)!;
      } else {
        nodeWithOffset = computeTreeNodeWithOffset(node)!;
      }
      if (classMember.isSourceDeclaration) {
        features.add(Tag.isSourceDeclaration);
      }
      if (classMember.isSynthesized) {
        features.add(Tag.isSynthesized);
        if (member.enclosingClass != node) {
          features[Tag.member] = memberQualifiedName(member);
        }
        if (classMember.hasDeclarations) {
          for (ClassMember declaration in classMember.declarations) {
            features.addElement(
                Tag.declarations, classMemberQualifiedName(declaration));
          }
        }
      }
      features[Tag.classBuilder] = classMember.classBuilder.name;

      Set<ClassMember>? declaredOverrides =
          data.declaredOverrides[data.aliasMap[classMember] ?? classMember];
      if (declaredOverrides != null) {
        for (ClassMember override in declaredOverrides) {
          features.addElement(
              Tag.declaredOverrides, classMemberQualifiedName(override));
        }
      }

      Set<ClassMember>? mixinApplicationOverrides = data
          .mixinApplicationOverrides[data.aliasMap[classMember] ?? classMember];
      if (mixinApplicationOverrides != null) {
        for (ClassMember override in mixinApplicationOverrides) {
          features.addElement(Tag.mixinApplicationOverrides,
              classMemberQualifiedName(override));
        }
      }

      Set<ClassMember>? inheritedImplements =
          data.inheritedImplements[data.aliasMap[classMember] ?? classMember];
      if (inheritedImplements != null) {
        for (ClassMember implement in inheritedImplements) {
          features.addElement(
              Tag.inheritedImplements, classMemberQualifiedName(implement));
        }
      }

      if (member.enclosingClass == node && member is Procedure) {
        switch (member.stubKind) {
          case ProcedureStubKind.Regular:
            // TODO: Handle this case.
            break;
          case ProcedureStubKind.AbstractForwardingStub:
            features.add(Tag.abstractForwardingStub);
            features[Tag.type] = procedureType(member);
            features[Tag.covariance] =
                classMember.getCovariance(_classHierarchyBuilder).toString();
            break;
          case ProcedureStubKind.ConcreteForwardingStub:
            features.add(Tag.concreteForwardingStub);
            features[Tag.type] = procedureType(member);
            features[Tag.covariance] =
                classMember.getCovariance(_classHierarchyBuilder).toString();
            features[Tag.stubTarget] = memberQualifiedName(member.stubTarget!);
            break;
          case ProcedureStubKind.NoSuchMethodForwarder:
            // TODO: Handle this case.
            break;
          case ProcedureStubKind.MemberSignature:
            features.add(Tag.memberSignature);
            features[Tag.type] = procedureType(member);
            features[Tag.covariance] =
                classMember.getCovariance(_classHierarchyBuilder).toString();
            break;
          case ProcedureStubKind.AbstractMixinStub:
            features.add(Tag.abstractMixinStub);
            break;
          case ProcedureStubKind.ConcreteMixinStub:
            features.add(Tag.concreteMixinStub);
            features[Tag.stubTarget] = memberQualifiedName(member.stubTarget!);
            break;
        }
      }

      registerValue(nodeWithOffset.location!.file, nodeWithOffset.fileOffset,
          id, features, member);
    }

    classHierarchyNode.classMemberMap
        .forEach((Name name, ClassMember classMember) {
      addMember(classMember, isSetter: false, isClassMember: true);
    });
    classHierarchyNode.classSetterMap
        .forEach((Name name, ClassMember classMember) {
      addMember(classMember, isSetter: true, isClassMember: true);
    });
    classHierarchyNode.interfaceMemberMap
        ?.forEach((Name name, ClassMember classMember) {
      if (!identical(classMember, classHierarchyNode.classMemberMap[name])) {
        addMember(classMember, isSetter: false, isClassMember: false);
      }
    });
    classHierarchyNode.interfaceSetterMap
        ?.forEach((Name name, ClassMember classMember) {
      if (!identical(classMember, classHierarchyNode.classSetterMap[name])) {
        addMember(classMember, isSetter: true, isClassMember: false);
      }
    });
  }

  @override
  Features computeClassValue(Id id, Class node) {
    Features features = new Features();
    ClassHierarchyNode classHierarchyNode =
        _classHierarchyBuilder.getNodeFromClass(node);
    ClassHierarchyNodeDataForTesting data = classHierarchyNode.dataForTesting!;
    classHierarchyNode.superclasses.forEach((Supertype supertype) {
      features.addElement(Tag.superclasses, supertypeToText(supertype));
    });
    classHierarchyNode.interfaces.forEach((Supertype supertype) {
      features.addElement(Tag.interfaces, supertypeToText(supertype));
    });
    if (data.abstractMembers.isNotEmpty) {
      for (ClassMember abstractMember in data.abstractMembers) {
        features.addElement(
            Tag.abstractMembers, classMemberQualifiedName(abstractMember));
      }
    }
    features[Tag.maxInheritancePath] =
        '${classHierarchyNode.maxInheritancePath}';
    if (classHierarchyNode.hasNoSuchMethod) {
      features.add(Tag.hasNoSuchMethod);
    }
    return features;
  }
}

String classMemberName(ClassMember classMember) {
  String name = classMember.name.text;
  if (classMember.forSetter) {
    name += '=';
  }
  return name;
}

String classMemberQualifiedName(ClassMember classMember) {
  return '${classMember.classBuilder.name}.${classMemberName(classMember)}';
}

String memberName(Member member) {
  String name = member.name.text;
  if (member is Procedure && member.isSetter) {
    name += '=';
  }
  return name;
}

String memberQualifiedName(Member member) {
  return '${member.enclosingClass!.name}.${memberName(member)}';
}

String procedureType(Procedure procedure) {
  if (procedure.kind == ProcedureKind.Getter) {
    return typeToText(procedure.function.returnType,
        TypeRepresentation.analyzerNonNullableByDefault);
  } else if (procedure.kind == ProcedureKind.Setter) {
    return typeToText(procedure.function.positionalParameters.single.type,
        TypeRepresentation.analyzerNonNullableByDefault);
  } else {
    Nullability functionTypeNullability;
    if (procedure.enclosingLibrary.isNonNullableByDefault) {
      functionTypeNullability = procedure.enclosingLibrary.nonNullable;
    } else {
      // We don't create a member signature when the member is just
      // a substitution. We should still take the nullability to be
      // legacy, though.
      functionTypeNullability = procedure.enclosingLibrary.nonNullable;
    }
    return typeToText(
        procedure.function.computeThisFunctionType(functionTypeNullability),
        TypeRepresentation.analyzerNonNullableByDefault);
  }
}
