// 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:args/args.dart' show ArgParser, ArgResults;
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/context/builder.dart';
import 'package:analyzer/src/context/context.dart' show AnalysisContextImpl;
import 'package:analyzer/src/dart/sdk/sdk.dart' show FolderBasedDartSdk;
import 'package:analyzer/src/generated/engine.dart'
    show AnalysisEngine, 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:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk;
import 'package:cli_util/cli_util.dart' show getSdkDir;
import 'package:path/path.dart' as path;

/// Options used to set up Source URI resolution in the analysis context.
class AnalyzerOptions {
  /// 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.
  final String packageRoot;

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

  /// Path to the dart-sdk. Null if `useMockSdk` is true or 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.
  final String dartSdkSummaryPath;

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

  AnalyzerOptions(
      {this.summaryPaths: const [],
      String dartSdkPath,
      this.dartSdkSummaryPath,
      this.customUrlMappings: const {},
      this.packageRoot: null,
      this.declaredVariables: const {}})
      : dartSdkPath = dartSdkPath ?? getSdkDir().path;

  factory AnalyzerOptions.fromArguments(
      ArgResults args, Map<String, String> declaredVariables) {
    var sdkPath = args['dart-sdk'] ?? getSdkDir().path;
    var sdkSummaryPath = args['dart-sdk-summary'];

    if (sdkSummaryPath == null) {
      sdkSummaryPath = path.join(sdkPath, 'lib', '_internal', 'ddc_sdk.sum');
    } else if (sdkSummaryPath == 'build') {
      // For building the SDK, we explicitly set the path to none.
      sdkSummaryPath = null;
    }

    return new AnalyzerOptions(
        summaryPaths: args['summary'] as List<String>,
        dartSdkPath: sdkPath,
        dartSdkSummaryPath: sdkSummaryPath,
        customUrlMappings: _parseUrlMappings(args['url-mapping']),
        packageRoot: args['package-root'],
        declaredVariables: declaredVariables);
  }

  static void addArguments(ArgParser parser) {
    parser
      ..addOption('summary',
          abbr: 's', help: 'summary file(s) to include', allowMultiple: true)
      ..addOption('dart-sdk',
          help: 'Dart SDK Path', defaultsTo: null, hide: true)
      ..addOption('dart-sdk-summary',
          help: 'Dart SDK Summary Path', defaultsTo: null, hide: true)
      ..addOption('package-root',
          abbr: 'p', help: 'Package root to resolve "package:" imports')
      ..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);
  }

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

/// Creates an analysis context that contains our restricted typing rules.
AnalysisContextImpl createAnalysisContext() {
  var res = AnalysisEngine.instance.createAnalysisContext();
  res.analysisOptions = new AnalysisOptionsImpl()
    ..strongMode = true
    ..trackCacheDependencies = false;
  return res;
}

/// Creates a SourceFactory configured by the [options].
///
/// Use [options.useMockSdk] to specify the SDK mode, or use [sdkResolver]
/// to entirely override the DartUriResolver.
///
/// 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() {
    ContextBuilderOptions builderOptions = new ContextBuilderOptions();
    if (options.packageRoot != null) {
      builderOptions.defaultPackagesDirectoryPath = options.packageRoot;
    }
    ContextBuilder builder = new ContextBuilder(resourceProvider, null, null,
        options: builderOptions);
    return new PackageMapUriResolver(resourceProvider,
        builder.convertPackagesToMap(builder.createPackageMap('')));
  }

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

FolderBasedDartSdk _createFolderBasedDartSdk(String sdkPath) {
  var resourceProvider = PhysicalResourceProvider.INSTANCE;
  var sdk = new FolderBasedDartSdk(resourceProvider,
      resourceProvider.getFolder(sdkPath), /*useDart2jsPaths:*/ true);
  sdk.useSummary = true;
  sdk.analysisOptions = new AnalysisOptionsImpl()..strongMode = true;
  return sdk;
}

/// Creates a [DartUriResolver] that uses the SDK at the given [sdkPath].
DartUriResolver createSdkPathResolver(String sdkSummaryPath, String sdkPath) {
  var sdk = (sdkSummaryPath != null)
      ? new SummaryBasedDartSdk(sdkSummaryPath, true)
      : _createFolderBasedDartSdk(sdkPath);
  return new DartUriResolver(sdk);
}

List<String> parseDeclaredVariables(
    List<String> args, Map<String, String> declaredVars) {
  var count = args.length;
  var remainingArgs = <String>[];
  for (int i = 0; i < count; i++) {
    var arg = args[i];
    if (arg == '--') {
      while (i < count) {
        remainingArgs.add(args[i++]);
      }
    } else if (arg.startsWith("-D")) {
      // The format for defined variables is:
      //     -D<name>=<value>
      var parts = arg.substring(2).split('=');
      declaredVars[parts[0]] = parts.length > 1 ? parts[1] : '';
    } else {
      remainingArgs.add(arg);
    }
  }
  return remainingArgs;
}
