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

/// 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);
  migrationTest.tearDown();
  print('Done.  Please point your browser to localhost:$port/\$filePath');
}

class MigrationBase {
  ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
  late MockServerChannel serverChannel;
  late 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();
  }

  /// 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'] as String;

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

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

  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] as String;
    } else {
      throw StateError('Unrecognized package $packageName');
    }
  }
}
