// Copyright (c) 2015, 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:analyzer/file_system/file_system.dart'
    show ResourceProvider, ResourceUriResolver;
import 'package:analyzer/file_system/physical_file_system.dart'
    show PhysicalResourceProvider;
import 'package:analyzer/source/custom_resolver.dart';
import 'package:analyzer/source/package_map_resolver.dart';
import 'package:analyzer/src/command_line/arguments.dart';
import 'package:analyzer/src/context/builder.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
import 'package:analyzer/src/generated/source.dart'
    show DartUriResolver, SourceFactory, UriResolver;
import 'package:analyzer/src/summary/package_bundle_reader.dart'
    show InSummaryUriResolver, SummaryDataStore;
import 'package:args/args.dart' show ArgParser, ArgResults;
import 'package:cli_util/cli_util.dart' show getSdkDir;
import 'package:path/path.dart' as path;

// ignore_for_file: deprecated_member_use

/// Options used to set up Source URI resolution in the analysis context.
class AnalyzerOptions {
  final ContextBuilderOptions contextBuilderOptions;

  /// Custom URI mappings, such as "dart:foo" -> "path/to/foo.dart"
  final Map<String, String> customUrlMappings;

  /// Package root when resolving 'package:' urls the standard way.
  String get packageRoot => contextBuilderOptions.defaultPackagesDirectoryPath;

  /// Path to the dart-sdk, or `null` if the path couldn't be determined.
  final String dartSdkPath;

  /// Path to the dart-sdk summary.  If this is set, it will be used in favor
  /// of the unsummarized one.
  String get dartSdkSummaryPath => contextBuilderOptions.dartSdkSummaryPath;

  /// Defined variables used by `bool.fromEnvironment` etc.
  Map<String, String> get declaredVariables =>
      contextBuilderOptions.declaredVariables;

  AnalyzerOptions._(
      {this.contextBuilderOptions,
      String dartSdkPath,
      this.customUrlMappings = const {}})
      : dartSdkPath = dartSdkPath ?? getSdkDir().path {
    contextBuilderOptions.declaredVariables ??= const {};
  }

  factory AnalyzerOptions.basic(
      {String dartSdkPath, String dartSdkSummaryPath}) {
    return AnalyzerOptions._(
        contextBuilderOptions: ContextBuilderOptions()
          ..defaultOptions = (AnalysisOptionsImpl()..previewDart2 = true)
          ..dartSdkSummaryPath = dartSdkSummaryPath,
        dartSdkPath: dartSdkPath);
  }

  factory AnalyzerOptions.fromArguments(ArgResults args,
      {String dartSdkSummaryPath}) {
    var contextOpts =
        createContextBuilderOptions(args, trackCacheDependencies: false);
    (contextOpts.defaultOptions as AnalysisOptionsImpl).previewDart2 = true;

    var dartSdkPath = args['dart-sdk'] as String ?? getSdkDir().path;

    dartSdkSummaryPath ??= contextOpts.dartSdkSummaryPath ??
        path.join(dartSdkPath, 'lib', '_internal', 'ddc_sdk.sum');
    // For building the SDK, we explicitly set the path to none.
    if (dartSdkSummaryPath == 'build') dartSdkSummaryPath = null;
    contextOpts.dartSdkSummaryPath = dartSdkSummaryPath;

    return AnalyzerOptions._(
        contextBuilderOptions: contextOpts,
        dartSdkPath: dartSdkPath,
        customUrlMappings:
            _parseUrlMappings(args['url-mapping'] as List<String>));
  }

  static void addArguments(ArgParser parser, {bool hide = true}) {
    parser.addOption('url-mapping',
        help: '--url-mapping=libraryUri,/path/to/library.dart uses\n'
            'library.dart as the source for an import of of "libraryUri".',
        allowMultiple: true,
        splitCommas: false,
        hide: hide);
  }

  static Map<String, String> _parseUrlMappings(List<String> argument) {
    var mappings = <String, String>{};
    for (var mapping in argument) {
      var splitMapping = mapping.split(',');
      if (splitMapping.length >= 2) {
        mappings[splitMapping[0]] = path.absolute(splitMapping[1]);
      }
    }
    return mappings;
  }
}

/// Creates a SourceFactory configured by the [options].
///
/// If supplied, [fileResolvers] will override the default `file:` and
/// `package:` URI resolvers.
SourceFactory createSourceFactory(AnalyzerOptions options,
    {DartUriResolver sdkResolver,
    List<UriResolver> fileResolvers,
    SummaryDataStore summaryData,
    ResourceProvider resourceProvider}) {
  resourceProvider ??= PhysicalResourceProvider.INSTANCE;
  var resolvers = <UriResolver>[sdkResolver];
  if (options.customUrlMappings.isNotEmpty) {
    resolvers
        .add(CustomUriResolver(resourceProvider, options.customUrlMappings));
  }
  if (summaryData != null) {
    resolvers.add(InSummaryUriResolver(resourceProvider, summaryData));
  }

  fileResolvers ??=
      createFileResolvers(options, resourceProvider: resourceProvider);
  resolvers.addAll(fileResolvers);
  return SourceFactory(resolvers, null, resourceProvider);
}

List<UriResolver> createFileResolvers(AnalyzerOptions options,
    {ResourceProvider resourceProvider}) {
  resourceProvider ??= PhysicalResourceProvider.INSTANCE;
  UriResolver packageResolver() {
    var builderOptions = ContextBuilderOptions();
    if (options.packageRoot != null) {
      builderOptions.defaultPackagesDirectoryPath = options.packageRoot;
    }
    var builder =
        ContextBuilder(resourceProvider, null, null, options: builderOptions);

    return PackageMapUriResolver(resourceProvider,
        builder.convertPackagesToMap(builder.createPackageMap('')));
  }

  return [ResourceUriResolver(resourceProvider), packageResolver()];
}
