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

// TODO(https://github.com/dart-lang/sdk/issues/48161): investigate whether or
// not machine mode is still relevant.

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

import 'package:devtools_shared/devtools_server.dart';
import 'package:devtools_shared/devtools_shared.dart';
import 'package:vm_service/vm_service.dart';

import '../../devtools_server.dart';
import 'utils.dart';

class MachineModeCommandHandler {
  static const launchDevToolsService = 'launchDevTools';
  static const copyAndCreateDevToolsFile = 'copyAndCreateDevToolsFile';
  static const restoreDevToolsFile = 'restoreDevToolsFiles';
  static const errorLaunchingBrowserCode = 500;
  static const bool machineMode = true;

  MachineModeCommandHandler({required this.server});

  /// The server instance associated with this client.
  final DevToolsServer server;

  // Only used for testing DevToolsUsage (used by survey).
  DevToolsUsage? _devToolsUsage;

  File? _devToolsBackup;

  static bool _isValidVmServiceUri(Uri? uri) {
    // Lots of things are considered valid URIs (including empty strings and
    // single letters) since they can be relative, so we need to do some extra
    // checks.
    return uri != null &&
        uri.isAbsolute &&
        (uri.isScheme('ws') ||
            uri.isScheme('wss') ||
            uri.isScheme('http') ||
            uri.isScheme('https'));
  }

  Future<void> initialize({
    required String devToolsUrl,
    required bool headlessMode,
  }) async {
    final Stream<Map<String, dynamic>> _stdinCommandStream = stdin
        .transform<String>(utf8.decoder)
        .transform<String>(const LineSplitter())
        .where((String line) => line.startsWith('{') && line.endsWith('}'))
        .map<Map<String, dynamic>>((String line) {
      return json.decode(line) as Map<String, dynamic>;
    });

    // Example input:
    // {
    //   "id":0,
    //   "method":"vm.register",
    //   "params":{
    //     "uri":"<vm-service-uri-here>",
    //   }
    // }
    _stdinCommandStream.listen((Map<String, dynamic> json) async {
      // ID can be String, int or null
      final dynamic id = json['id'];
      final Map<String, dynamic> params = json['params'];
      final method = json['method'];
      switch (method) {
        case 'vm.register':
          await _handleVmRegister(id, params, headlessMode, devToolsUrl);
          break;
        case 'devTools.launch':
          await _handleDevToolsLaunch(id, params, headlessMode, devToolsUrl);
          break;
        case 'client.list':
          _handleClientsList(id, params);
          break;
        case 'devTools.survey':
          _handleDevToolsSurvey(id, params);
          break;
        default:
          DevToolsUtils.printOutput(
            'Unknown method $method',
            {
              'id': id,
              'error': 'Unknown method $method',
            },
            machineMode: machineMode,
          );
      }
    });
  }

  Future<void> _handleVmRegister(
    dynamic id,
    Map<String, dynamic> params,
    bool headlessMode,
    String devToolsUrl,
  ) async {
    if (!params.containsKey('uri')) {
      DevToolsUtils.printOutput(
        'Invalid input: $params does not contain the key \'uri\'',
        {
          'id': id,
          'error': 'Invalid input: $params does not contain the key \'uri\'',
        },
        machineMode: machineMode,
      );
    }

    // params['uri'] should contain a vm service uri.
    final uri = Uri.tryParse(params['uri']);

    if (_isValidVmServiceUri(uri)) {
      await registerLaunchDevToolsService(
        uri!,
        id,
        devToolsUrl,
        headlessMode,
      );
    } else {
      DevToolsUtils.printOutput(
        'Uri must be absolute with a http, https, ws or wss scheme',
        {
          'id': id,
          'error': 'Uri must be absolute with a http, https, ws or wss scheme',
        },
        machineMode: machineMode,
      );
    }
  }

  Future<void> _handleDevToolsLaunch(
    dynamic id,
    Map<String, dynamic> params,
    bool headlessMode,
    String devToolsUrl,
  ) async {
    if (!params.containsKey('vmServiceUri')) {
      DevToolsUtils.printOutput(
        "Invalid input: $params does not contain the key 'vmServiceUri'",
        {
          'id': id,
          'error':
              "Invalid input: $params does not contain the key e'vmServiceUri'",
        },
        machineMode: machineMode,
      );
    }

    // params['vmServiceUri'] should contain a vm service uri.
    final vmServiceUri = Uri.tryParse(params['vmServiceUri'])!;

    if (_isValidVmServiceUri(vmServiceUri)) {
      try {
        final result = await server.launchDevTools(
          params,
          vmServiceUri,
          devToolsUrl,
          headlessMode,
          machineMode,
        );
        DevToolsUtils.printOutput(
          'DevTools launched',
          {'id': id, 'result': result},
          machineMode: machineMode,
        );
      } catch (e, s) {
        DevToolsUtils.printOutput(
          'Failed to launch browser: $e\n$s',
          {'id': id, 'error': 'Failed to launch browser: $e\n$s'},
          machineMode: machineMode,
        );
      }
    } else {
      DevToolsUtils.printOutput(
        'VM Service URI must be absolute with a http, https, ws or wss scheme',
        {
          'id': id,
          'error':
              'VM Service Uri must be absolute with a http, https, ws or wss scheme',
        },
        machineMode: machineMode,
      );
    }
  }

  void _handleClientsList(dynamic id, Map<String, dynamic> params) {
    DevToolsUtils.printOutput(
      server.clientManager.toString(),
      server.clientManager.toJson(id),
      machineMode: machineMode,
    );
  }

  void _handleDevToolsSurvey(dynamic id, Map<String, dynamic> params) {
    _devToolsUsage ??= DevToolsUsage();
    final String surveyRequest = params['surveyRequest'];
    final String value = params['value'];

    switch (surveyRequest) {
      case copyAndCreateDevToolsFile:
        // Backup and delete ~/.devtools file.
        if (backupAndCreateDevToolsStore()) {
          _devToolsUsage = null;
          DevToolsUtils.printOutput(
            'DevTools Survey',
            {
              'id': id,
              'result': {
                // TODO(bkonyi): fix incorrect spelling of "success" here and
                // below once we figure out the impact of changing this key.
                'success': true,
              },
            },
            machineMode: machineMode,
          );
        }
        break;
      case restoreDevToolsFile:
        _devToolsUsage = null;
        final content = restoreDevToolsStore();
        if (content != null) {
          DevToolsUtils.printOutput(
            'DevTools Survey',
            {
              'id': id,
              'result': {
                'success': true,
                'content': content,
              },
            },
            machineMode: machineMode,
          );

          _devToolsUsage = null;
        }
        break;
      case apiSetActiveSurvey:
        _devToolsUsage!.activeSurvey = value;
        DevToolsUtils.printOutput(
          'DevTools Survey',
          {
            'id': id,
            'result': {
              'success': _devToolsUsage!.activeSurvey == value,
              'activeSurvey': _devToolsUsage!.activeSurvey,
            },
          },
          machineMode: machineMode,
        );
        break;
      case apiGetSurveyActionTaken:
        DevToolsUtils.printOutput(
          'DevTools Survey',
          {
            'id': id,
            'result': {
              'activeSurvey': _devToolsUsage!.activeSurvey,
              'surveyActionTaken': _devToolsUsage!.surveyActionTaken,
            },
          },
          machineMode: machineMode,
        );
        break;
      case apiSetSurveyActionTaken:
        _devToolsUsage!.surveyActionTaken = jsonDecode(value);
        DevToolsUtils.printOutput(
          'DevTools Survey',
          {
            'id': id,
            'result': {
              'activeSurvey': _devToolsUsage!.activeSurvey,
              'surveyActionTaken': _devToolsUsage!.surveyActionTaken,
            },
          },
          machineMode: machineMode,
        );
        break;
      case apiGetSurveyShownCount:
        DevToolsUtils.printOutput(
          'DevTools Survey',
          {
            'id': id,
            'result': {
              'activeSurvey': _devToolsUsage!.activeSurvey,
              'surveyShownCount': _devToolsUsage!.surveyShownCount,
            },
          },
          machineMode: machineMode,
        );
        break;
      case apiIncrementSurveyShownCount:
        _devToolsUsage!.incrementSurveyShownCount();
        DevToolsUtils.printOutput(
          'DevTools Survey',
          {
            'id': id,
            'result': {
              'activeSurvey': _devToolsUsage!.activeSurvey,
              'surveyShownCount': _devToolsUsage!.surveyShownCount,
            },
          },
          machineMode: machineMode,
        );
        break;
      default:
        DevToolsUtils.printOutput(
          'Unknown DevTools Survey Request $surveyRequest',
          {
            'id': id,
            'result': {
              'activeSurvey': _devToolsUsage!.activeSurvey,
              'surveyActionTaken': _devToolsUsage!.surveyActionTaken,
              'surveyShownCount': _devToolsUsage!.surveyShownCount,
            },
          },
          machineMode: machineMode,
        );
    }
  }

  bool backupAndCreateDevToolsStore() {
    assert(_devToolsBackup == null);
    final devToolsStore = File(
      LocalFileSystem.devToolsStoreLocation(),
    );
    if (devToolsStore.existsSync()) {
      _devToolsBackup = devToolsStore
          .copySync('${LocalFileSystem.devToolsDir()}/.devtools_backup_test');
      devToolsStore.deleteSync();
    }
    return true;
  }

  String? restoreDevToolsStore() {
    if (_devToolsBackup != null) {
      // Read the current ~/.devtools file
      LocalFileSystem.maybeMoveLegacyDevToolsStore();

      final devToolsStore = File(LocalFileSystem.devToolsStoreLocation());
      final content = devToolsStore.readAsStringSync();

      // Delete the temporary ~/.devtools file
      devToolsStore.deleteSync();
      if (_devToolsBackup!.existsSync()) {
        // Restore the backup ~/.devtools file we created in
        // backupAndCreateDevToolsStore.
        _devToolsBackup!.copySync(LocalFileSystem.devToolsStoreLocation());
        _devToolsBackup!.deleteSync();
        _devToolsBackup = null;
      }
      return content;
    }
    return null;
  }

  Future<void> registerLaunchDevToolsService(
    Uri vmServiceUri,
    dynamic id,
    String devToolsUrl,
    bool headlessMode,
  ) async {
    try {
      // Connect to the vm service and register a method to launch DevTools in
      // chrome.
      final service = await DevToolsUtils.connectToVmService(vmServiceUri);
      if (service == null) return;

      service.registerServiceCallback(
        launchDevToolsService,
        (params) async {
          try {
            await server.launchDevTools(
              params,
              vmServiceUri,
              devToolsUrl,
              headlessMode,
              machineMode,
            );
            return {
              'result': Success().toJson(),
            };
          } catch (e, s) {
            // Note: It's critical that we return responses in exactly the right format
            // or the VM will unregister the service. The objects must match JSON-RPC
            // however a successful response must also have a "type" field in its result.
            // Otherwise, we can return an error object (instead of result) that includes
            // code + message.
            return {
              'error': {
                'code': errorLaunchingBrowserCode,
                'message': 'Failed to launch browser: $e\n$s',
              },
            };
          }
        },
      );

      final registerServiceMethodName = 'registerService';
      await service.callMethod(registerServiceMethodName, args: {
        'service': launchDevToolsService,
        'alias': 'DevTools Server',
      });

      DevToolsUtils.printOutput(
        'Successfully registered launchDevTools service',
        {
          'id': id,
          'result': {'success': true},
        },
        machineMode: machineMode,
      );
    } catch (e) {
      DevToolsUtils.printOutput(
        'Unable to connect to VM service at $vmServiceUri: $e',
        {
          'id': id,
          'error': 'Unable to connect to VM service at $vmServiceUri: $e',
        },
        machineMode: machineMode,
      );
    }
  }
}
