// 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/fasta/kernel/kernel_api.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';

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);
  }
}
