// Copyright 2014 The Flutter Authors. 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:meta/meta.dart';

import '../application_package.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../build_info.dart';
import '../device.dart';
import '../features.dart';
import '../globals.dart' as globals;
import '../project.dart';
import 'chrome.dart';

class WebApplicationPackage extends ApplicationPackage {
  WebApplicationPackage(this.flutterProject) : super(id: flutterProject.manifest.appName);

  final FlutterProject flutterProject;

  @override
  String get name => flutterProject.manifest.appName;

  /// The location of the web source assets.
  Directory get webSourcePath => flutterProject.directory.childDirectory('web');
}

class ChromeDevice extends Device {
  ChromeDevice() : super(
      'chrome',
      category: Category.web,
      platformType: PlatformType.web,
      ephemeral: false,
  );

  /// The active chrome instance.
  Chrome _chrome;

  // TODO(jonahwilliams): this is technically false, but requires some refactoring
  // to allow hot mode restart only devices.
  @override
  bool get supportsHotReload => true;

  @override
  bool get supportsHotRestart => true;

  @override
  bool get supportsStartPaused => true;

  @override
  bool get supportsFlutterExit => true;

  @override
  bool get supportsScreenshot => false;

  @override
  void clearLogs() { }

  DeviceLogReader _logReader;

  @override
  DeviceLogReader getLogReader({ApplicationPackage app}) {
    return _logReader ??= NoOpDeviceLogReader(app?.name);
  }

  @override
  Future<bool> installApp(ApplicationPackage app) async => true;

  @override
  Future<bool> isAppInstalled(ApplicationPackage app) async => true;

  @override
  Future<bool> isLatestBuildInstalled(ApplicationPackage app) async => true;

  @override
  Future<bool> get isLocalEmulator async => false;

  @override
  Future<String> get emulatorId async => null;

  @override
  bool isSupported() =>  featureFlags.isWebEnabled && chromeLauncher.canFindChrome();

  @override
  String get name => 'Chrome';

  @override
  DevicePortForwarder get portForwarder => const NoOpDevicePortForwarder();

  @override
  Future<String> get sdkNameAndVersion async => _sdkNameAndVersion ??= await _computeSdkNameAndVersion();

  String _sdkNameAndVersion;
  Future<String> _computeSdkNameAndVersion() async {
    if (!isSupported()) {
      return 'unknown';
    }
    // See https://bugs.chromium.org/p/chromium/issues/detail?id=158372
    String version = 'unknown';
    if (globals.platform.isWindows) {
      final ProcessResult result = await globals.processManager.run(<String>[
        r'reg', 'query', 'HKEY_CURRENT_USER\\Software\\Google\\Chrome\\BLBeacon', '/v', 'version',
      ]);
      if (result.exitCode == 0) {
        final List<String> parts = (result.stdout as String).split(RegExp(r'\s+'));
        if (parts.length > 2) {
          version = 'Google Chrome ' + parts[parts.length - 2];
        }
      }
    } else {
      final String chrome = findChromeExecutable();
      final ProcessResult result = await globals.processManager.run(<String>[
        chrome,
        '--version',
      ]);
      if (result.exitCode == 0) {
        version = result.stdout as String;
      }
    }
    return version.trim();
  }

  @override
  Future<LaunchResult> startApp(
    covariant WebApplicationPackage package, {
    String mainPath,
    String route,
    DebuggingOptions debuggingOptions,
    Map<String, Object> platformArgs,
    bool prebuiltApplication = false,
    bool ipv6 = false,
  }) async {
    // See [ResidentWebRunner.run] in flutter_tools/lib/src/resident_web_runner.dart
    // for the web initialization and server logic.
    final String url = platformArgs['uri'] as String;
    _chrome = await chromeLauncher.launch(url,
      dataDir: globals.fs.currentDirectory
        .childDirectory('.dart_tool')
        .childDirectory('chrome-device'));

    globals.logger.sendEvent('app.webLaunchUrl', <String, dynamic>{'url': url, 'launched': true});

    return LaunchResult.succeeded(observatoryUri: null);
  }

  @override
  Future<bool> stopApp(ApplicationPackage app) async {
    await _chrome?.close();
    return true;
  }

  @override
  Future<TargetPlatform> get targetPlatform async => TargetPlatform.web_javascript;

  @override
  Future<bool> uninstallApp(ApplicationPackage app) async => true;

  @override
  bool isSupportedForProject(FlutterProject flutterProject) {
    return flutterProject.web.existsSync();
  }

  @override
  Future<void> dispose() async {
    _logReader?.dispose();
    await portForwarder?.dispose();
  }
}

class WebDevices extends PollingDeviceDiscovery {
  WebDevices() : super('chrome');

  final bool _chromeIsAvailable = chromeLauncher.canFindChrome();
  final ChromeDevice _webDevice = ChromeDevice();
  final WebServerDevice _webServerDevice = WebServerDevice();

  @override
  bool get canListAnything => featureFlags.isWebEnabled;

  @override
  Future<List<Device>> pollingGetDevices() async {
    return <Device>[
      if (_chromeIsAvailable)
        _webDevice,
      _webServerDevice,
    ];
  }

  @override
  bool get supportsPlatform =>  featureFlags.isWebEnabled;
}

@visibleForTesting
String parseVersionForWindows(String input) {
  return input.split(RegExp('\w')).last;
}


/// A special device type to allow serving for arbitrary browsers.
class WebServerDevice extends Device {
  WebServerDevice() : super(
    'web-server',
    platformType: PlatformType.web,
    category: Category.web,
    ephemeral: false,
  );

  @override
  void clearLogs() { }

  @override
  Future<String> get emulatorId => null;

  DeviceLogReader _logReader;

  @override
  DeviceLogReader getLogReader({ApplicationPackage app}) {
    return _logReader ??= NoOpDeviceLogReader(app?.name);
  }

  @override
  Future<bool> installApp(ApplicationPackage app) async => true;

  @override
  Future<bool> isAppInstalled(ApplicationPackage app) async => true;

  @override
  Future<bool> isLatestBuildInstalled(ApplicationPackage app) async => true;

  @override
  Future<bool> get isLocalEmulator async => false;

  @override
  bool isSupported() => featureFlags.isWebEnabled;

  @override
  bool isSupportedForProject(FlutterProject flutterProject) {
    return flutterProject.web.existsSync();
  }

  @override
  String get name => 'Web Server';

  @override
  DevicePortForwarder get portForwarder => const NoOpDevicePortForwarder();

  @override
  Future<String> get sdkNameAndVersion async => 'Flutter Tools';

  @override
  Future<LaunchResult> startApp(ApplicationPackage package, {
    String mainPath,
    String route,
    DebuggingOptions debuggingOptions,
    Map<String, Object> platformArgs,
    bool prebuiltApplication = false,
    bool ipv6 = false,
  }) async {
    final String url = platformArgs['uri'] as String;
    if (debuggingOptions.startPaused) {
      globals.printStatus('Waiting for connection from Dart debug extension at $url', emphasis: true);
    } else {
      globals.printStatus('$mainPath is being served at $url', emphasis: true);
    }
    globals.logger.sendEvent('app.webLaunchUrl', <String, dynamic>{'url': url, 'launched': false});
    return LaunchResult.succeeded(observatoryUri: null);
  }

  @override
  Future<bool> stopApp(ApplicationPackage app) async {
    return true;
  }

  @override
  Future<TargetPlatform> get targetPlatform async => TargetPlatform.web_javascript;

  @override
  Future<bool> uninstallApp(ApplicationPackage app) async {
    return true;
  }

  @override
  Future<void> dispose() async {
    _logReader?.dispose();
    await portForwarder?.dispose();
  }
}
