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

  /// List of summary file paths.
  final List<String> summaryPaths;

  final Map<String, String> customSummaryModules = {};

  /// 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,
      List<String> summaryPaths,
      String dartSdkPath,
      this.customUrlMappings: const {}})
      : dartSdkPath = dartSdkPath ?? getSdkDir().path,
        summaryPaths = summaryPaths ?? const [] {
    contextBuilderOptions.declaredVariables ??= const {};
    _parseCustomSummaryModules();
  }

  factory AnalyzerOptions.basic(
      {String dartSdkPath,
      String dartSdkSummaryPath,
      List<String> summaryPaths}) {
    var contextBuilderOptions = new ContextBuilderOptions()
      ..defaultOptions = (new AnalysisOptionsImpl()
        ..strongMode = true
        ..previewDart2 = true)
      ..dartSdkSummaryPath = dartSdkSummaryPath;

    return new AnalyzerOptions._(
        contextBuilderOptions: contextBuilderOptions,
        dartSdkPath: dartSdkPath,
        summaryPaths: summaryPaths);
  }

  factory AnalyzerOptions.fromArguments(ArgResults args,
      {String dartSdkSummaryPath, List<String> summaryPaths}) {
    var contextBuilderOptions = createContextBuilderOptions(args,
        strongMode: true, trackCacheDependencies: false);
    (contextBuilderOptions.defaultOptions as AnalysisOptionsImpl).previewDart2 =
        true;

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

    dartSdkSummaryPath ??= contextBuilderOptions.dartSdkSummaryPath;
    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;
    contextBuilderOptions.dartSdkSummaryPath = dartSdkSummaryPath;

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

  static void addArguments(ArgParser parser, {bool hide: true}) {
    parser
      ..addOption('summary',
          abbr: 's', help: 'summary file(s) to include', allowMultiple: true)
      ..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(Iterable 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;
  }

  /// A summary path can contain "=" followed by an explicit module name to
  /// allow working with summaries whose physical location is outside of the
  /// module root directory.
  ///
  /// Removes any explicit module names from [summaryPaths] and populates with
  /// [customSummaryModules] with them.
  void _parseCustomSummaryModules() {
    for (var i = 0; i < summaryPaths.length; i++) {
      var summaryPath = summaryPaths[i];
      var pipe = summaryPath.indexOf("=");
      if (pipe != -1) {
        summaryPaths[i] = summaryPath.substring(0, pipe);
        customSummaryModules[summaryPaths[i]] = summaryPath.substring(pipe + 1);
      }
    }
  }
}

/// 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>[];
  if (options.customUrlMappings.isNotEmpty) {
    resolvers.add(
        new CustomUriResolver(resourceProvider, options.customUrlMappings));
  }
  resolvers.add(sdkResolver);
  if (summaryData != null) {
    resolvers.add(new InSummaryUriResolver(resourceProvider, summaryData));
  }

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

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

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

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