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

@JS()
library hot_reload_client;

import 'dart:async';
import 'dart:convert';
import 'dart:html';

import 'package:dwds/data/build_result.dart';
import 'package:dwds/data/connect_request.dart';
import 'package:dwds/data/devtools_request.dart';
import 'package:dwds/data/error_response.dart';
import 'package:dwds/data/run_request.dart';
import 'package:dwds/data/serializers.dart';
import 'package:dwds/src/sockets.dart';
import 'package:js/js.dart';
import 'package:sse/client/sse_client.dart';
import 'package:uuid/uuid.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

import 'promise.dart';
import 'reloader/legacy_restarter.dart';
import 'reloader/manager.dart';
import 'reloader/require_restarter.dart';
import 'reloader/restarter.dart';
import 'run_main.dart';

// GENERATE:
// pub run build_runner build web
Future<void> main() {
  try {
    sendMessage('pebbhcjfokadbgbnlmogdkkaahmamnap', 'injected-client-started',
        RequestOptions(), allowInterop(([e]) {
      if (e == null) {
        // Error sending message. Check lastError to silently fail.
        lastError;
      }
    }));
  } catch (_) {}

  return runZonedGuarded(() async {
    // Set the unique id for this instance of the app.
    // Test apps may already have this set.
    dartAppInstanceId ??= const Uuid().v1();

    var fixedPath = _fixProtocol(dwdsDevHandlerPath);
    var fixedUri = Uri.parse(fixedPath);
    var client = fixedUri.isScheme('ws') || fixedUri.isScheme('wss')
        ? WebSocketClient(WebSocketChannel.connect(fixedUri))
        : SseSocketClient(SseClient(fixedPath));

    Restarter restarter;
    if (dartModuleStrategy == 'require-js') {
      restarter = await RequireRestarter.create();
    } else if (dartModuleStrategy == 'legacy') {
      restarter = LegacyRestarter();
    } else {
      throw StateError('Unknown module strategy: $dartModuleStrategy');
    }

    var manager = ReloadingManager(client, restarter);

    hotRestartJs = allowInterop(() {
      return toPromise(manager.hotRestart());
    });

    launchDevToolsJs = allowInterop(() {
      if (!_isChromium) {
        window.alert(
            'Dart DevTools is only supported on Chromium based browsers.');
        return;
      }
      client.sink.add(jsonEncode(serializers.serialize(DevToolsRequest((b) => b
        ..appId = dartAppId
        ..instanceId = dartAppInstanceId))));
    });

    client.stream.listen((serialized) async {
      var event = serializers.deserialize(jsonDecode(serialized));
      if (event is BuildResult) {
        if (reloadConfiguration == 'ReloadConfiguration.liveReload') {
          manager.reloadPage();
        } else if (reloadConfiguration == 'ReloadConfiguration.hotRestart') {
          await manager.hotRestart();
        } else if (reloadConfiguration == 'ReloadConfiguration.hotReload') {
          print('Hot reload is currently unsupported. Ignoring change.');
        }
      } else if (event is DevToolsResponse) {
        if (!event.success) {
          var alert = 'DevTools failed to open with:\n${event.error}';
          if (event.promptExtension && window.confirm(alert)) {
            window.open('https://goo.gle/dart-debug-extension', '_blank');
          } else {
            window.alert(alert);
          }
        }
      } else if (event is RunRequest) {
        runMain();
      } else if (event is ErrorResponse) {
        window.console.error('Error from backend:\n\nError: ${event.error}\n\n'
            'Stack Trace:\n${event.stackTrace}');
      }
    }, onError: (error) {
      // An error is propagated on a full page reload as Chrome presumably
      // forces the SSE connection to close in a bad state. This does not cause
      // any adverse effects so simply swallow this error as to not print the
      // misleading unhandled error message.
    });

    if (dwdsEnableDevtoolsLaunch) {
      window.onKeyDown.listen((Event e) {
        if (e is KeyboardEvent &&
            const [
              'd',
              'D',
              '∂', // alt-d output on Mac
              'Î', // shift-alt-D output on Mac
            ].contains(e.key) &&
            e.altKey &&
            !e.ctrlKey &&
            !e.metaKey) {
          e.preventDefault();
          launchDevToolsJs();
        }
      });
    }

    if (_isChromium) {
      client.sink.add(jsonEncode(serializers.serialize(ConnectRequest((b) => b
        ..appId = dartAppId
        ..instanceId = dartAppInstanceId
        ..entrypointPath = dartEntrypointPath))));
    } else {
      // If not Chromium we just invoke main, devtools aren't supported.
      runMain();
    }
  }, (error, stackTrace) {
    print('''
Unhandled error detected in the injected client.js script.

You can disable this script in webdev by passing --no-injected-client if it
is preventing your app from loading, but note that this will also prevent
all debugging and hot reload/restart functionality from working.

The original error is below, please file an issue at
https://github.com/dart-lang/webdev/issues/new and attach this output:

$error
$stackTrace
''');
  });
}

/// Returns [url] modified if necessary so that, if the current page is served
/// over `https`, then the URL is converted to `https`.
String _fixProtocol(String url) {
  var uri = Uri.parse(url);
  if (window.location.protocol == 'https:' &&
      uri.scheme == 'http' &&
      // Chrome allows mixed content on localhost. It is not safe to assume the
      // server is also listening on https.
      uri.host != 'localhost') {
    uri = uri.replace(scheme: 'https');
  } else if (window.location.protocol == 'wss:' &&
      uri.scheme == 'ws' &&
      uri.host != 'localhost') {
    uri = uri.replace(scheme: 'wss');
  }
  return uri.toString();
}

@JS(r'$dartAppId')
external String get dartAppId;

@JS(r'$dartAppInstanceId')
external String get dartAppInstanceId;

@JS(r'$dwdsDevHandlerPath')
external String get dwdsDevHandlerPath;

@JS(r'$dartAppInstanceId')
external set dartAppInstanceId(String id);

@JS(r'$dartModuleStrategy')
external String get dartModuleStrategy;

@JS(r'$dartHotRestart')
external set hotRestartJs(Promise<bool> Function() cb);

@JS(r'$launchDevTools')
external void Function() get launchDevToolsJs;

@JS(r'$launchDevTools')
external set launchDevToolsJs(void Function() cb);

@JS(r'$dartReloadConfiguration')
external String get reloadConfiguration;

@JS(r'$dartEntrypointPath')
external String get dartEntrypointPath;

@JS(r'$dwdsEnableDevtoolsLaunch')
external bool get dwdsEnableDevtoolsLaunch;

@JS()
class ChromeError {
  external String get message;
}

// Note: Not checking the lastError when one occurs throws a runtime exception.
@JS('chrome.runtime.lastError')
external ChromeError get lastError;

@JS()
@anonymous
class RequestOptions {}

@JS('chrome.runtime.sendMessage')
external void sendMessage(
    String id, Object message, Object options, Function callback);

bool get _isChromium => window.navigator.userAgent.contains('Chrome');
