// Copyright (c) 2022, 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:_fe_analyzer_shared/src/messages/diagnostic_message.dart';
import 'package:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/target/targets.dart';
import 'package:kernel/type_environment.dart';

import '../api_prototype/compiler_options.dart';
import '../api_prototype/kernel_generator.dart';
import '../api_prototype/terminal_color_support.dart';
import '../base/command_line_reporting.dart';
import '../codes/cfe_codes.dart';
import '../compute_platform_binaries_location.dart';
import '../kernel_generator_impl.dart';

typedef PerformAnalysisFunction = void Function(
    DiagnosticMessageHandler onDiagnostic, Component component);
typedef UriFilter = bool Function(Uri uri);

/// Analysis the [entryPoints] using [performAnalysis].
Future<void> runAnalysis(
    List<Uri> entryPoints, PerformAnalysisFunction performAnalysis) async {
  CompilerOptions options = new CompilerOptions();
  options.sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
  await _runAnalysis(options, entryPoints, performAnalysis);
}

/// Analysis the platform libraries for [target] using [performAnalysis].
Future<void> runPlatformAnalysis(
    Target target, PerformAnalysisFunction performAnalysis) async {
  CompilerOptions options = new CompilerOptions();
  options.target = target;
  options.environmentDefines = {};
  options.librariesSpecificationUri =
      Uri.base.resolve('sdk/lib/libraries.json');
  Set<Uri> additionalSources = {};
  for (String extraRequiredLibrary in target.extraRequiredLibraries) {
    additionalSources.add(Uri.parse(extraRequiredLibrary));
  }
  for (String extraRequiredLibrary in target.extraRequiredLibrariesPlatform) {
    additionalSources.add(Uri.parse(extraRequiredLibrary));
  }
  await _runAnalysis(
      options, [Uri.parse('dart:core'), ...additionalSources], performAnalysis);
}

Future<void> _runAnalysis(CompilerOptions options, Iterable<Uri> entryPoints,
    PerformAnalysisFunction performAnalysis) async {
  options.packagesFileUri = Uri.base.resolve('.dart_tool/package_config.json');
  options.onDiagnostic = (DiagnosticMessage message) {
    printDiagnosticMessage(message, print);
  };
  InternalCompilerResult compilerResult = await kernelForProgramInternal(
    entryPoints.first,
    options,
    retainDataForTesting: true,
    requireMain: false,
    additionalSources: entryPoints.skip(1).toList(),
  ) as InternalCompilerResult;

  performAnalysis(options.onDiagnostic!, compilerResult.component!);
}

class StaticTypeVisitorBase extends RecursiveVisitor {
  final TypeEnvironment typeEnvironment;

  StaticTypeContext? staticTypeContext;

  StaticTypeVisitorBase(Component component, ClassHierarchy classHierarchy)
      : typeEnvironment =
            new TypeEnvironment(new CoreTypes(component), classHierarchy);

  @override
  void visitProcedure(Procedure node) {
    if (node.kind == ProcedureKind.Factory && node.isRedirectingFactory) {
      // Don't visit redirecting factories.
      return;
    }
    staticTypeContext = new StaticTypeContext(node, typeEnvironment);
    super.visitProcedure(node);
    staticTypeContext = null;
  }

  @override
  void visitField(Field node) {
    staticTypeContext = new StaticTypeContext(node, typeEnvironment);
    super.visitField(node);
    staticTypeContext = null;
  }

  @override
  void visitConstructor(Constructor node) {
    staticTypeContext = new StaticTypeContext(node, typeEnvironment);
    super.visitConstructor(node);
    staticTypeContext = null;
  }
}

class AnalysisVisitor extends StaticTypeVisitorBase {
  final DiagnosticMessageHandler onDiagnostic;
  final Component component;
  final UriFilter? uriFilter;
  late final AnalysisInterface interface;

  Map<String, Map<String, List<FormattedMessage>>> _messages = {};

  AnalysisVisitor(this.onDiagnostic, this.component, this.uriFilter)
      : super(component,
            new ClassHierarchy(component, new CoreTypes(component))) {
    interface = new AnalysisInterface(this);
  }

  @override
  void visitLibrary(Library node) {
    if (uriFilter != null) {
      if (uriFilter!(node.importUri)) {
        super.visitLibrary(node);
      }
    } else {
      super.visitLibrary(node);
    }
  }

  void registerMessage(TreeNode node, String message) {
    Location location = node.location!;
    Uri uri = location.file;
    String uriString = relativizeUri(uri)!;
    Map<String, List<FormattedMessage>> actualMap = _messages.putIfAbsent(
        uriString, () => <String, List<FormattedMessage>>{});
    if (uri.isScheme('org-dartlang-sdk')) {
      location = new Location(Uri.base.resolve(uri.path.substring(1)),
          location.line, location.column);
    }
    LocatedMessage locatedMessage = templateUnspecified
        .withArguments(message)
        .withLocation(uri, node.fileOffset, noLength);
    FormattedMessage diagnosticMessage = locatedMessage.withFormatting(
        formatWithLocationNoSdk(locatedMessage, Severity.warning,
            location: location, uriToSource: component.uriToSource),
        location.line,
        location.column,
        Severity.warning,
        []);
    actualMap
        .putIfAbsent(message, () => <FormattedMessage>[])
        .add(diagnosticMessage);
  }

  void forEachMessage(
      void Function(String, Map<String, List<FormattedMessage>>) f) {
    _messages.forEach(f);
  }

  Map<String, List<FormattedMessage>>? getMessagesForUri(String uri) {
    return _messages[uri];
  }

  void printMessages() {
    forEachMessage((String uri, Map<String, List<FormattedMessage>> messages) {
      messages.forEach((String message, List<FormattedMessage> actualMessages) {
        for (FormattedMessage message in actualMessages) {
          onDiagnostic(message);
        }
      });
    });
  }
}

/// Convenience interface for performing analysis.
class AnalysisInterface {
  final AnalysisVisitor _visitor;
  final ComponentLookup _componentLookup;

  AnalysisInterface(this._visitor)
      : _componentLookup = new ComponentLookup(_visitor.component);

  void reportMessage(TreeNode node, String message) {
    _visitor.registerMessage(node, message);
  }

  InterfaceType createInterfaceType(String className,
      {String? uri, List<DartType>? typeArguments}) {
    LibraryLookup libraryLookup =
        _componentLookup.getLibrary(Uri.parse(uri ?? 'dart:core'));
    ClassLookup classLookup = libraryLookup.getClass(className);
    Class cls = classLookup.cls;
    return new InterfaceType(
        cls,
        Nullability.nonNullable,
        typeArguments ??
            new List<DartType>.generate(
                cls.typeParameters.length, (index) => const DynamicType()));
  }

  bool isSubtypeOf(DartType subtype, DartType supertype) {
    return _visitor.typeEnvironment
        .isSubtypeOf(subtype, supertype, SubtypeCheckMode.withNullabilities);
  }
}

typedef GeneralAnalysisFunction = void Function(
    TreeNode node, AnalysisInterface interface);

/// Generalized analyzer that uses a single [GeneralAnalysisFunction] on all
/// [TreeNode]s.
class GeneralAnalyzer extends AnalysisVisitor {
  final GeneralAnalysisFunction analyzer;

  GeneralAnalyzer(DiagnosticMessageHandler onDiagnostic, Component component,
      bool Function(Uri uri)? analyzedUrisFilter, this.analyzer)
      : super(onDiagnostic, component, analyzedUrisFilter);

  @override
  void defaultTreeNode(TreeNode node) {
    analyzer(node, interface);
    super.defaultTreeNode(node);
  }
}

/// Returns a function that will perform [analysisFunction] on [TreeNode]s
/// in a component, using [uriFilter] to filter which libraries that will be
/// visited.
PerformAnalysisFunction performGeneralAnalysis(
    UriFilter? uriFilter, GeneralAnalysisFunction analysisFunction) {
  return (DiagnosticMessageHandler onDiagnostic, Component component) {
    GeneralAnalyzer analyzer = new GeneralAnalyzer(
        onDiagnostic, component, uriFilter, analysisFunction);
    component.accept(analyzer);
    analyzer.printMessages();
  };
}

/// Helper class for looking up libraries in a [Component].
class ComponentLookup {
  final Component _component;

  ComponentLookup(this._component);

  Map<Uri, LibraryLookup>? _libraries;

  LibraryLookup getLibrary(Uri uri) {
    LibraryLookup? libraryLookup = (_libraries ??= new Map.fromIterable(
        _component.libraries,
        key: (library) => library.importUri,
        value: (library) => new LibraryLookup(library)))[uri];
    if (libraryLookup == null) {
      throw "Couldn't find library for '$uri'.";
    }
    return libraryLookup;
  }
}

/// Helper class for looking up classes and members in a [Library].
// TODO(johnniwinther): Support member lookup.
class LibraryLookup {
  final Library library;

  LibraryLookup(this.library);

  Map<String, ClassLookup>? _classes;

  ClassLookup getClass(String name) {
    ClassLookup? classLookup = (_classes ??= new Map.fromIterable(
        library.classes,
        key: (cls) => cls.name,
        value: (cls) => new ClassLookup(cls)))[name];
    if (classLookup == null) {
      throw "Couldn't find class '$name' in ${library.importUri}.";
    }
    return classLookup;
  }
}

/// Helper class for looking up members in a [Class].
// TODO(johnniwinther): Support member lookup.
class ClassLookup {
  final Class cls;

  ClassLookup(this.cls);
}

/// Entry points used for analyzing cfe source code.
// TODO(johnniwinther): Update this to include all files in the cfe, and not
//  only those reachable from 'compiler.dart'.
final List<Uri> cfeOnlyEntryPoints = [
  Uri.base.resolve('pkg/front_end/tool/compile.dart')
];

/// Filter function used to only analyze cfe source code.
bool cfeOnly(Uri uri) {
  String text = '$uri';
  for (String path in [
    'package:_fe_analyzer_shared/',
    'package:kernel/',
    'package:front_end/',
  ]) {
    if (text.startsWith(path)) {
      return true;
    }
  }
  return false;
}

/// Entry points used for analyzing cfe and backend source code.
// TODO(johnniwinther): Update this to include all files in cfe and backends,
//  and not only those reachable from these entry points.
List<Uri> cfeAndBackendsEntryPoints = [
  Uri.base.resolve('pkg/front_end/tool/compile.dart'),
  Uri.base.resolve('pkg/vm/lib/kernel_front_end.dart'),
  Uri.base.resolve('pkg/compiler/lib/src/dart2js.dart'),
  Uri.base.resolve('pkg/dev_compiler/bin/dartdevc.dart'),
  Uri.base.resolve('pkg/frontend_server/bin/frontend_server_starter.dart'),
];

/// Filter function used to only analyze cfe and backend source code.
bool cfeAndBackends(Uri uri) {
  String text = '$uri';
  for (String path in [
    'package:_fe_analyzer_shared/',
    'package:kernel/',
    'package:front_end/',
    'package:frontend_server/',
    'package:vm/',
    'package:compiler/',
    'package:dartdevc/',
    'package:_js_interop_checks/',
  ]) {
    if (text.startsWith(path)) {
      return true;
    }
  }
  return false;
}

/// Filter function used to only analyze platform code.
bool platformOnly(Uri uri) => uri.isScheme('dart');
