// Copyright (c) 2019, 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.

// @dart = 2.9

/// This executable provides the ability to run the migration tool in process
/// on a single package.  It should be invoked with two command-line arguments:
/// a path to a configuration file and the name of a package to migrate.
///
/// The configuration file format is a JSON map, with the following keys:
/// - `sdk_root`: path to the SDK source code on the user's machine (this is the
///   directory that contains `pkg`, `third_party`, `tests`, etc.
/// - `output_root`: if present, path to the directory on the user's machine
///   where output HTML files should go.  A subdirectory will be created for
///   each package that is migrated.
/// - `external_packages`: a map (name => path) of additional non-SDK packages
///   that may need to be migrated.
/// - `port`: if present, the port where a server should be spawned serving HTML
///   pages.
library migration_runner;

import 'dart:convert';
import 'dart:io' as io;

import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/server/crash_reporting_attachments.dart';
import 'package:analysis_server/src/utilities/mocks.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:cli_util/cli_util.dart';
import 'package:path/path.dart' as path;
import 'package:test/test.dart';

Future<void> main(List<String> args) async {
  if (args.length != 2) {
    throw StateError(
        'Exactly two arguments are required: the path to a JSON configuration '
        'file, and the name of the package to migrate');
  }
  var testInfoJsonPath = args[0];
  var testInfoJson = json.decode(io.File(testInfoJsonPath).readAsStringSync());
  var packageName = args[1];
  var testInfo = TestInfo(testInfoJson);
  var packageRoot = testInfo.packageRoot(packageName);
  var port = testInfo.port;
  print('Preparing to migrate');
  var migrationTest = MigrationTest();
  migrationTest.setUp();
  print('Migrating');
  await migrationTest.run(packageRoot, port);
  if (port == null) {
    print('Done');
    io.exit(0);
  } else {
    print('Done.  Please point your browser to localhost:$port/\$filePath');
  }
}

class MigrationBase {
  ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
  MockServerChannel serverChannel;
  AnalysisServer server;

  AnalysisServer createAnalysisServer() {
    //
    // Create server
    //
    var options = AnalysisServerOptions();
    var sdkPath = getSdkPath();
    return AnalysisServer(
        serverChannel,
        resourceProvider,
        options,
        DartSdkManager(sdkPath),
        CrashReportingAttachmentsBuilder.empty,
        InstrumentationService.NULL_SERVICE);
  }

  void processNotification(Notification notification) {
    if (notification.event == SERVER_NOTIFICATION_ERROR) {
      fail('${notification.toJson()}');
    }
  }

  Future<Response> sendAnalysisSetAnalysisRoots(List<String> directories) {
    var request =
        AnalysisSetAnalysisRootsParams(directories, []).toRequest('0');
    return waitResponse(request);
  }

  Future<Response> sendEditDartfix(List<String> directories, int port) {
    var request = EditDartfixParams(directories,
            includedFixes: ['non-nullable'], port: port)
        .toRequest('1');
    return waitResponse(request);
  }

  void setUp() {
    serverChannel = MockServerChannel();
    server = createAnalysisServer();
    server.pluginManager = TestPluginManager();
    // listen for notifications
    var notificationStream = serverChannel.notificationController.stream;
    notificationStream.listen((Notification notification) {
      processNotification(notification);
    });
  }

  void tearDown() {
    server.done();
    server = null;
    serverChannel = null;
  }

  /// Returns a [Future] that completes when the server's analysis is complete.
  Future waitForTasksFinished() {
    return server.onAnalysisComplete;
  }

  /// Completes with a successful [Response] for the given [request].
  Future<Response> waitResponse(Request request,
      {bool throwOnError = true}) async {
    return serverChannel.sendRequest(request, throwOnError: throwOnError);
  }
}

class MigrationTest extends MigrationBase {
  Future<void> run(String packageRoot, int port) async {
    var packageRoots = <String>[packageRoot];
    await sendAnalysisSetAnalysisRoots(packageRoots);
    await sendEditDartfix(packageRoots, port);
  }
}

class TestInfo {
  static const Set<String> thirdPartyPackages = {
    'charcode',
    'collection',
    'logging',
    'meta',
    'pedantic',
    'typed_data'
  };

  static const Set<String> builtInPackages = {'meta', 'path'};

  final Map<String, Object> testInfoJson;

  TestInfo(this.testInfoJson);

  Map<String, String> get externalPackages =>
      ((testInfoJson['external_packages'] ?? {}) as Map).cast<String, String>();

  String get outputRoot => testInfoJson['output_root'];

  int get port => testInfoJson['port'];

  String get sdkRoot => testInfoJson['sdk_root'];

  String packageRoot(String packageName) {
    if (thirdPartyPackages.contains(packageName)) {
      return path.join(sdkRoot, 'third_party', 'pkg', packageName);
    } else if (builtInPackages.contains(packageName)) {
      return path.join(sdkRoot, 'pkg', packageName);
    } else if (externalPackages.containsKey(packageName)) {
      return externalPackages[packageName];
    } else {
      throw StateError('Unrecognized package $packageName');
    }
  }
}
