// 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 'dart:io' as io;
import 'dart:isolate';
import 'dart:typed_data';

import 'package:analyzer/dart/analysis/context_locator.dart' as api;
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/context/context.dart';
import 'package:analyzer/src/context/packages.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/cache.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart'
    as api;
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/source/source_resource.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk;
import 'package:analyzer/src/summary2/bundle_reader.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/package_bundle_format.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer_cli/src/context_cache.dart';
import 'package:analyzer_cli/src/driver.dart';
import 'package:analyzer_cli/src/error_formatter.dart';
import 'package:analyzer_cli/src/error_severity.dart';
import 'package:analyzer_cli/src/has_context_mixin.dart';
import 'package:analyzer_cli/src/options.dart';
import 'package:bazel_worker/bazel_worker.dart';
import 'package:collection/collection.dart';
import 'package:convert/convert.dart';

/// Persistent Bazel worker.
class AnalyzerWorkerLoop extends AsyncWorkerLoop {
  final ResourceProvider resourceProvider;
  final PerformanceLog logger = PerformanceLog(null);
  final String dartSdkPath;
  WorkerPackageBundleCache packageBundleCache;

  final StringBuffer errorBuffer = StringBuffer();
  final StringBuffer outBuffer = StringBuffer();

  AnalyzerWorkerLoop(this.resourceProvider, AsyncWorkerConnection connection,
      {this.dartSdkPath})
      : super(connection: connection) {
    packageBundleCache =
        WorkerPackageBundleCache(resourceProvider, logger, 256 * 1024 * 1024);
  }

  factory AnalyzerWorkerLoop.sendPort(
      ResourceProvider resourceProvider, SendPort sendPort,
      {String dartSdkPath}) {
    AsyncWorkerConnection connection = SendPortAsyncWorkerConnection(sendPort);
    return AnalyzerWorkerLoop(resourceProvider, connection,
        dartSdkPath: dartSdkPath);
  }

  factory AnalyzerWorkerLoop.std(ResourceProvider resourceProvider,
      {io.Stdin stdinStream, io.Stdout stdoutStream, String dartSdkPath}) {
    AsyncWorkerConnection connection = StdAsyncWorkerConnection(
        inputStream: stdinStream, outputStream: stdoutStream);
    return AnalyzerWorkerLoop(resourceProvider, connection,
        dartSdkPath: dartSdkPath);
  }

  /// Performs analysis with given [options].
  Future<void> analyze(
      CommandLineOptions options, Map<String, WorkerInput> inputs) async {
    var packageBundleProvider =
        WorkerPackageBundleProvider(packageBundleCache, inputs);
    var buildMode = BuildMode(resourceProvider, options, AnalysisStats(),
        ContextCache(resourceProvider, options, Driver.verbosePrint),
        logger: logger, packageBundleProvider: packageBundleProvider);
    await buildMode.analyze();
    AnalysisEngine.instance.clearCaches();
  }

  /// Perform a single loop step.
  @override
  Future<WorkResponse> performRequest(WorkRequest request) async {
    return logger.runAsync('Perform request', () async {
      errorBuffer.clear();
      outBuffer.clear();
      try {
        // Prepare inputs with their digests.
        var inputs = <String, WorkerInput>{};
        for (var input in request.inputs) {
          inputs[input.path] = WorkerInput(input.path, input.digest);
        }

        // Add in the dart-sdk argument if `dartSdkPath` is not null,
        // otherwise it will try to find the currently installed sdk.
        var arguments = request.arguments.toList();
        if (dartSdkPath != null &&
            !arguments.any((arg) => arg.startsWith('--dart-sdk'))) {
          arguments.add('--dart-sdk=$dartSdkPath');
        }

        // Prepare options.
        var options = CommandLineOptions.parse(resourceProvider, arguments,
            printAndFail: (String msg) {
          throw ArgumentError(msg);
        });

        // Analyze and respond.
        await analyze(options, inputs);
        var msg = _getErrorOutputBuffersText();
        return WorkResponse()
          ..exitCode = EXIT_CODE_OK
          ..output = msg;
      } catch (e, st) {
        var msg = _getErrorOutputBuffersText();
        msg += '$e\n$st';
        return WorkResponse()
          ..exitCode = EXIT_CODE_ERROR
          ..output = msg;
      }
    });
  }

  /// Run the worker loop.
  @override
  Future<void> run() async {
    errorSink = errorBuffer;
    outSink = outBuffer;
    exitHandler = (int exitCode) {
      throw StateError('Exit called: $exitCode');
    };
    await super.run();
  }

  String _getErrorOutputBuffersText() {
    var msg = '';
    if (errorBuffer.isNotEmpty) {
      msg += errorBuffer.toString() + '\n';
    }
    if (outBuffer.isNotEmpty) {
      msg += outBuffer.toString() + '\n';
    }
    return msg;
  }
}

/// Analyzer used when the "--build-mode" option is supplied.
class BuildMode with HasContextMixin {
  @override
  final ResourceProvider resourceProvider;
  final CommandLineOptions options;
  final AnalysisStats stats;
  final PerformanceLog logger;
  final PackageBundleProvider packageBundleProvider;

  @override
  final ContextCache contextCache;

  SummaryDataStore summaryDataStore;
  AnalysisOptionsImpl analysisOptions;
  Map<Uri, File> uriToFileMap;
  final List<Source> explicitSources = <Source>[];

  SourceFactory sourceFactory;
  DeclaredVariables declaredVariables;
  AnalysisDriver analysisDriver;

  LinkedElementFactory elementFactory;

  // May be null.
  final DependencyTracker dependencyTracker;

  BuildMode(this.resourceProvider, this.options, this.stats, this.contextCache,
      {PerformanceLog logger, PackageBundleProvider packageBundleProvider})
      : logger = logger ?? PerformanceLog(null),
        packageBundleProvider = packageBundleProvider ??
            DirectPackageBundleProvider(resourceProvider),
        dependencyTracker = options.summaryDepsOutput != null
            ? DependencyTracker(options.summaryDepsOutput)
            : null;

  bool get _shouldOutputSummary =>
      options.buildSummaryOutput != null ||
      options.buildSummaryOutputSemantic != null;

  /// Perform package analysis according to the given [options].
  Future<ErrorSeverity> analyze() async {
    return await logger.runAsync('Analyze', () async {
      // Write initial progress message.
      if (!options.machineFormat) {
        outSink.writeln("Analyzing ${options.sourceFiles.join(', ')}...");
      }

      // Create the URI to file map.
      uriToFileMap = _createUriToFileMap(options.sourceFiles);
      if (uriToFileMap == null) {
        io.exitCode = ErrorSeverity.ERROR.ordinal;
        return ErrorSeverity.ERROR;
      }

      // BuildMode expects sourceFiles in the format "<uri>|<filepath>",
      // but the rest of the code base does not understand this format.
      // Rewrite sourceFiles, stripping the "<uri>|" prefix, so that it
      // does not cause problems with code that does not expect this format.
      options.rewriteSourceFiles(options.sourceFiles
          .map((String uriPipePath) =>
              uriPipePath.substring(uriPipePath.indexOf('|') + 1))
          .toList());

      // Prepare the analysis driver.
      try {
        logger.run('Prepare analysis driver', () {
          _createAnalysisDriver();
        });
      } on ConflictingSummaryException catch (e) {
        errorSink.writeln('$e');
        io.exitCode = ErrorSeverity.ERROR.ordinal;
        return ErrorSeverity.ERROR;
      }

      // Add sources.
      for (var uri in uriToFileMap.keys) {
        var file = uriToFileMap[uri];
        if (!file.exists) {
          errorSink.writeln('File not found: ${file.path}');
          io.exitCode = ErrorSeverity.ERROR.ordinal;
          return ErrorSeverity.ERROR;
        }
        Source source = FileSource(file, uri);
        explicitSources.add(source);
      }

      // Write summary.
      if (_shouldOutputSummary) {
        await logger.runAsync('Build and write output summary', () async {
          // Build and assemble linked libraries.
          var bytes = _computeLinkedLibraries2();

          // Write the whole package bundle.
          // TODO(scheglov) Remove support for `buildSummaryOutput`.
          if (options.buildSummaryOutput != null) {
            var file = io.File(options.buildSummaryOutput);
            file.writeAsBytesSync(bytes, mode: io.FileMode.writeOnly);
          }
          if (options.buildSummaryOutputSemantic != null) {
            var file = io.File(options.buildSummaryOutputSemantic);
            file.writeAsBytesSync(bytes, mode: io.FileMode.writeOnly);
          }
        });
      } else {
        // Build the graph, e.g. associate parts with libraries.
        for (var file in uriToFileMap.values) {
          analysisDriver.fsState.getFileForPath(file.path);
        }
      }

      ErrorSeverity severity;
      if (options.buildSummaryOnly) {
        severity = ErrorSeverity.NONE;
      } else {
        // Process errors.
        await _printErrors(outputPath: options.buildAnalysisOutput);
        severity = await _computeMaxSeverity();
      }

      if (dependencyTracker != null) {
        var file = io.File(dependencyTracker.outputPath);
        file.writeAsStringSync(dependencyTracker.dependencies.join('\n'));
      }

      return severity;
    });
  }

  /// Use [elementFactory] filled with input summaries, and link libraries
  /// in [explicitSources] to produce linked summary bytes.
  Uint8List _computeLinkedLibraries2() {
    return logger.run('Link output summary2', () {
      var inputLibraries = <LinkInputLibrary>[];

      for (var librarySource in explicitSources) {
        var path = librarySource.fullName;

        var parseResult = analysisDriver.parseFileSync(path);
        if (parseResult == null) {
          throw ArgumentError('No parsed unit for $path');
        }

        var unit = parseResult.unit;
        var isPart = unit.directives.any((d) => d is PartOfDirective);
        if (isPart) {
          continue;
        }

        var inputUnits = <LinkInputUnit>[];
        inputUnits.add(
          LinkInputUnit(null, librarySource, false, unit),
        );

        for (var directive in unit.directives) {
          if (directive is PartDirective) {
            var partUri = directive.uri.stringValue;
            var partSource = sourceFactory.resolveUri(librarySource, partUri);

            // Add empty synthetic units for unresolved `part` URIs.
            if (partSource == null) {
              continue;
            }

            var partPath = partSource.fullName;
            var partParseResult = analysisDriver.parseFileSync(partPath);
            if (partParseResult == null) {
              throw ArgumentError('No parsed unit for part $partPath in $path');
            }
            inputUnits.add(
              LinkInputUnit(
                partUri,
                partSource,
                false,
                partParseResult.unit,
              ),
            );
          }
        }

        inputLibraries.add(
          LinkInputLibrary(librarySource, inputUnits),
        );
      }

      var linkResult = link(elementFactory, inputLibraries, false);

      var bundleBuilder = PackageBundleBuilder();
      for (var library in inputLibraries) {
        bundleBuilder.addLibrary(
          library.uriStr,
          library.units.map((e) => e.uriStr).toList(),
        );
      }
      return bundleBuilder.finish(
        astBytes: linkResult.astBytes,
        resolutionBytes: linkResult.resolutionBytes,
      );
    });
  }

  Future<ErrorSeverity> _computeMaxSeverity() async {
    var maxSeverity = ErrorSeverity.NONE;
    if (!options.buildSuppressExitCode) {
      for (var source in explicitSources) {
        var result = await analysisDriver.getErrors(source.fullName);
        for (var error in result.errors) {
          var processedSeverity = determineProcessedSeverity(
              error, options, analysisDriver.analysisOptions);
          if (processedSeverity != null) {
            maxSeverity = maxSeverity.max(processedSeverity);
          }
        }
      }
    }
    return maxSeverity;
  }

  void _createAnalysisDriver() {
    // Read the summaries.
    summaryDataStore = SummaryDataStore(<String>[]);

    // Adds a bundle at `path` to `summaryDataStore`.
    PackageBundleReader addBundle(String path) {
      var bundle = packageBundleProvider.get(path);
      summaryDataStore.addBundle(path, bundle);
      return bundle;
    }

    SummaryBasedDartSdk sdk;
    logger.run('Add SDK bundle', () {
      sdk = SummaryBasedDartSdk(options.dartSdkSummaryPath, true);
      summaryDataStore.addBundle(null, sdk.bundle);
    });

    var numInputs = options.buildSummaryInputs.length;
    logger.run('Add $numInputs input summaries', () {
      for (var path in options.buildSummaryInputs) {
        addBundle(path);
      }
    });

    var rootPath =
        options.sourceFiles.isEmpty ? null : options.sourceFiles.first;

    var packages = _findPackages(rootPath);

    sourceFactory = SourceFactory(<UriResolver>[
      DartUriResolver(sdk),
      TrackingInSummaryUriResolver(
          InSummaryUriResolver(resourceProvider, summaryDataStore),
          dependencyTracker),
      ExplicitSourceResolver(uriToFileMap)
    ]);

    analysisOptions =
        createAnalysisOptionsForCommandLineOptions(options, rootPath);

    var scheduler = AnalysisDriverScheduler(logger);
    analysisDriver = AnalysisDriver(
      scheduler,
      logger,
      resourceProvider,
      MemoryByteStore(),
      FileContentOverlay(),
      null,
      sourceFactory,
      analysisOptions,
      externalSummaries: summaryDataStore,
      packages: packages,
    );

    _setAnalysisDriverAnalysisContext(rootPath);

    declaredVariables = DeclaredVariables.fromMap(options.definedVariables);
    analysisDriver.declaredVariables = declaredVariables;

    _createLinkedElementFactory();

    scheduler.start();
  }

  void _createLinkedElementFactory() {
    var analysisContext = AnalysisContextImpl(
      SynchronousSession(analysisOptions, declaredVariables),
      sourceFactory,
    );

    elementFactory = LinkedElementFactory(
      analysisContext,
      AnalysisSessionImpl(null),
      Reference.root(),
    );

    for (var bundle in summaryDataStore.bundles) {
      elementFactory.addBundle(
        BundleReader(
          elementFactory: elementFactory,
          astBytes: bundle.astBytes,
          resolutionBytes: bundle.resolutionBytes,
        ),
      );
    }
  }

  /// Convert [sourceEntities] (a list of file specifications of the form
  /// "$uri|$path") to a map from URI to path. If an error occurs, report the
  /// error and return null.
  Map<Uri, File> _createUriToFileMap(List<String> sourceEntities) {
    var uriToFileMap = <Uri, File>{};
    for (var sourceFile in sourceEntities) {
      var pipeIndex = sourceFile.indexOf('|');
      if (pipeIndex == -1) {
        // TODO(paulberry): add the ability to guess the URI from the path.
        errorSink.writeln(
            'Illegal input file (must be "\$uri|\$path"): $sourceFile');
        return null;
      }
      var uri = Uri.parse(sourceFile.substring(0, pipeIndex));
      var path = sourceFile.substring(pipeIndex + 1);
      path = resourceProvider.pathContext.absolute(path);
      path = resourceProvider.pathContext.normalize(path);
      uriToFileMap[uri] = resourceProvider.getFile(path);
    }
    return uriToFileMap;
  }

  Packages _findPackages(String path) {
    var configPath = options.packageConfigPath;
    if (configPath != null) {
      var configFile = resourceProvider.getFile(configPath);
      return parsePackagesFile(resourceProvider, configFile);
    }

    if (path != null) {
      var file = resourceProvider.getFile(path);
      return findPackagesFrom(resourceProvider, file);
    }

    return Packages.empty;
  }

  /// Print errors for all explicit sources. If [outputPath] is supplied, output
  /// is sent to a new file at that path.
  Future<void> _printErrors({String outputPath}) async {
    await logger.runAsync('Compute and print analysis errors', () async {
      var buffer = StringBuffer();
      var severityProcessor = (AnalysisError error) =>
          determineProcessedSeverity(error, options, analysisOptions);
      var formatter = options.machineFormat
          ? MachineErrorFormatter(buffer, options, stats,
              severityProcessor: severityProcessor)
          : HumanErrorFormatter(buffer, options, stats,
              severityProcessor: severityProcessor);
      for (var source in explicitSources) {
        var result = await analysisDriver.getErrors(source.fullName);
        formatter.formatErrors([result]);
      }
      formatter.flush();
      if (!options.machineFormat) {
        stats.print(buffer);
      }
      if (outputPath == null) {
        var sink = options.machineFormat ? errorSink : outSink;
        sink.write(buffer);
      } else {
        io.File(outputPath).writeAsStringSync(buffer.toString());
      }
    });
  }

  void _setAnalysisDriverAnalysisContext(String rootPath) {
    if (rootPath == null) {
      return;
    }

    var apiContextRoots = api.ContextLocator(
      resourceProvider: resourceProvider,
    ).locateRoots(
      includedPaths: [rootPath],
      excludedPaths: [],
    );

    if (apiContextRoots.isEmpty) {
      return;
    }

    analysisDriver.configure(
      analysisContext: api.DriverBasedAnalysisContext(
        resourceProvider,
        apiContextRoots.first,
        analysisDriver,
      ),
    );
  }
}

/// Tracks paths to dependencies, really just a thin api around a Set<String>.
class DependencyTracker {
  final _dependencies = <String>{};

  /// The path to the file to create once tracking is done.
  final String outputPath;

  DependencyTracker(this.outputPath);

  Iterable<String> get dependencies => _dependencies;

  void record(String path) => _dependencies.add(path);
}

/// [PackageBundleProvider] that always reads from the [ResourceProvider].
class DirectPackageBundleProvider implements PackageBundleProvider {
  final ResourceProvider resourceProvider;

  DirectPackageBundleProvider(this.resourceProvider);

  @override
  PackageBundleReader get(String path) {
    var bytes = io.File(path).readAsBytesSync();
    return PackageBundleReader(bytes);
  }
}

/// Instances of the class [ExplicitSourceResolver] map URIs to files on disk
/// using a fixed mapping provided at construction time.
class ExplicitSourceResolver extends UriResolver {
  final Map<Uri, File> uriToFileMap;
  final Map<String, Uri> pathToUriMap;

  /// Construct an [ExplicitSourceResolver] based on the given [uriToFileMap].
  ExplicitSourceResolver(Map<Uri, File> uriToFileMap)
      : uriToFileMap = uriToFileMap,
        pathToUriMap = _computePathToUriMap(uriToFileMap);

  @override
  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
    var file = uriToFileMap[uri];
    actualUri ??= uri;
    if (file == null) {
      return null;
    } else {
      return FileSource(file, actualUri);
    }
  }

  @override
  Uri restoreAbsolute(Source source) {
    return pathToUriMap[source.fullName];
  }

  /// Build the inverse mapping of [uriToSourceMap].
  static Map<String, Uri> _computePathToUriMap(Map<Uri, File> uriToSourceMap) {
    var pathToUriMap = <String, Uri>{};
    uriToSourceMap.forEach((Uri uri, File file) {
      pathToUriMap[file.path] = uri;
    });
    return pathToUriMap;
  }
}

/// Provider for [PackageBundleReader]s by file paths.
abstract class PackageBundleProvider {
  /// Return the [PackageBundleReader] for the file with the given [path].
  PackageBundleReader get(String path);
}

/// Wrapper for [InSummaryUriResolver] that tracks accesses to summaries.
class TrackingInSummaryUriResolver extends UriResolver {
  // May be null.
  final DependencyTracker dependencyTracker;
  final InSummaryUriResolver inSummaryUriResolver;

  TrackingInSummaryUriResolver(
      this.inSummaryUriResolver, this.dependencyTracker);

  @override
  Source resolveAbsolute(Uri uri, [Uri actualUri]) {
    var source = inSummaryUriResolver.resolveAbsolute(uri, actualUri);
    if (dependencyTracker != null &&
        source != null &&
        source is InSummarySource) {
      dependencyTracker.record(source.summaryPath);
    }
    return source;
  }
}

/// Worker input.
///
/// Bazel does not specify the format of the digest, so we cannot assume that
/// the digest itself is enough to uniquely identify inputs. So, we use a pair
/// of path + digest.
class WorkerInput {
  static const _digestEquality = ListEquality<int>();

  final String path;
  final List<int> digest;

  WorkerInput(this.path, this.digest);

  @override
  int get hashCode => _digestEquality.hash(digest);

  @override
  bool operator ==(Object other) {
    return other is WorkerInput &&
        other.path == path &&
        _digestEquality.equals(other.digest, digest);
  }

  @override
  String toString() => '$path @ ${hex.encode(digest)}';
}

/// Value object for [WorkerPackageBundleCache].
class WorkerPackageBundle {
  final List<int> bytes;
  final PackageBundleReader bundle;

  WorkerPackageBundle(this.bytes, this.bundle);

  /// Approximation of a bundle size in memory.
  int get size => bytes.length * 3;
}

/// Cache of [PackageBundleReader]s.
class WorkerPackageBundleCache {
  final ResourceProvider resourceProvider;
  final PerformanceLog logger;
  final Cache<WorkerInput, WorkerPackageBundle> _cache;

  WorkerPackageBundleCache(this.resourceProvider, this.logger, int maxSizeBytes)
      : _cache = Cache<WorkerInput, WorkerPackageBundle>(
            maxSizeBytes, (value) => value.size);

  /// Get the [PackageBundleReader] from the file with the given [path] in the context
  /// of the given worker [inputs].
  PackageBundleReader get(Map<String, WorkerInput> inputs, String path) {
    var input = inputs[path];

    // The input must be not null, otherwise we're not expected to read
    // this file, but we check anyway to be safe.
    if (input == null) {
      logger.writeln('Read $path outside of the inputs.');
      var file = resourceProvider.getFile(path);
      var bytes = file.readAsBytesSync() as Uint8List;
      return PackageBundleReader(bytes);
    }

    return _cache.get(input, () {
      logger.writeln('Read $input.');
      var file = resourceProvider.getFile(path);
      var bytes = file.readAsBytesSync() as Uint8List;
      var bundle = PackageBundleReader(bytes);
      return WorkerPackageBundle(bytes, bundle);
    }).bundle;
  }
}

/// [PackageBundleProvider] that reads from [WorkerPackageBundleCache] using
/// the request specific [inputs].
class WorkerPackageBundleProvider implements PackageBundleProvider {
  final WorkerPackageBundleCache cache;
  final Map<String, WorkerInput> inputs;

  WorkerPackageBundleProvider(this.cache, this.inputs);

  @override
  PackageBundleReader get(String path) {
    return cache.get(inputs, path);
  }
}
