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

// @dart = 2.15

// ignore_for_file: implementation_imports

import 'dart:async';
import 'dart:io' as io;
import 'dart:typed_data';

import 'package:_fe_analyzer_shared/src/macros/compiler/request_channel.dart';
import 'package:front_end/src/api_prototype/compiler_options.dart' as fe;
import 'package:front_end/src/api_prototype/file_system.dart' as fe;
import 'package:front_end/src/api_prototype/kernel_generator.dart' as fe;
import 'package:front_end/src/base/nnbd_mode.dart' as fe;
import 'package:front_end/src/fasta/kernel/utils.dart' as fe;
import 'package:kernel/ast.dart' as fe;
import 'package:kernel/target/targets.dart' as fe;
import 'package:vm/kernel_front_end.dart' as vm;
import 'package:vm/target/vm.dart' as vm;

Future<void> runBinaryProtocol(String addressStr) async {
  final parsedAddress = _ParsedAddress.parse(addressStr);
  final socket = await io.Socket.connect(
    parsedAddress.host,
    parsedAddress.port,
  );

  _Client(
    RequestChannel(socket),
    () {
      socket.destroy();
    },
  );
}

class _Client {
  final RequestChannel _channel;
  final void Function() _stopHandler;
  final Map<Uri, Uint8List> _dills = {};

  _Client(this._channel, this._stopHandler) {
    _channel.add('dill.put', _dillPut);
    _channel.add('dill.remove', _dillRemove);
    _channel.add('exit', _exit);
    _channel.add('kernelForModule', _kernelForModule);
    _channel.add('kernelForProgram', _kernelForProgram);
    _channel.add('stop', _stop);
  }

  Future<void> _dillPut(Object? argumentObject) async {
    final arguments = argumentObject.argumentAsMap;
    final uriStr = arguments.required<String>('uri');
    final bytes = arguments.required<Uint8List>('bytes');

    final uri = Uri.parse(uriStr);
    _dills[uri] = bytes;
  }

  Future<void> _dillRemove(Object? argumentObject) async {
    final arguments = argumentObject.argumentAsMap;
    final uriStr = arguments.required<String>('uri');

    final uri = Uri.parse(uriStr);
    _dills.remove(uri);
  }

  Future<void> _exit(Object? argument) async {
    io.exit(0);
  }

  fe.CompilerOptions _getCompilerOptions(Map<Object?, Object?> arguments) {
    final sdkSummaryUriStr = arguments.required<String>('sdkSummary');

    final compilerOptions = fe.CompilerOptions()
      ..environmentDefines = {}
      ..fileSystem = _FileSystem(_channel, _dills)
      ..nnbdMode = fe.NnbdMode.Strong
      ..sdkSummary = Uri.parse(sdkSummaryUriStr)
      ..target = vm.VmTarget(fe.TargetFlags());

    final additionalDills = arguments['additionalDills'].asListOf<String>();
    if (additionalDills != null) {
      compilerOptions.additionalDills.addAll(
        additionalDills.map(Uri.parse),
      );
    }

    return compilerOptions;
  }

  Future<Object?> _kernelForModule(Object? argumentObject) async {
    final arguments = argumentObject.argumentAsMap;
    final packagesFileUriStr = arguments.required<String>('packagesFileUri');

    final compilerOptions = _getCompilerOptions(arguments)
      ..packagesFileUri = Uri.parse(packagesFileUriStr);

    final uriStrList = arguments['uris'].asListOf<String>();
    if (uriStrList == null) {
      throw ArgumentError('Missing field: uris');
    }

    final compilationResults = await fe.kernelForModule(
      uriStrList.map(Uri.parse).toList(),
      compilerOptions,
    );

    return _serializeComponentWithoutPlatform(
      compilationResults.component!,
    );
  }

  Future<Object?> _kernelForProgram(Object? argumentObject) async {
    final arguments = argumentObject.argumentAsMap;

    final compilerOptions = _getCompilerOptions(arguments);

    final packagesFileUriStr = arguments.optional<String>('packagesFileUri');
    if (packagesFileUriStr != null) {
      compilerOptions.packagesFileUri = Uri.parse(packagesFileUriStr);
    }

    final uriStr = arguments.required<String>('uri');

    final compilationResults = await vm.compileToKernel(
      Uri.parse(uriStr),
      compilerOptions,
      environmentDefines: {},
    );

    return _serializeComponentWithoutPlatform(
      compilationResults.component!,
    );
  }

  Future<void> _stop(Object? argument) async {
    _stopHandler();
  }

  static Uint8List _serializeComponentWithoutPlatform(fe.Component component) {
    return fe.serializeComponent(
      component,
      filter: (library) {
        return !library.importUri.isScheme('dart');
      },
      includeSources: true,
    );
  }
}

class _FileSystem implements fe.FileSystem {
  final RequestChannel _channel;
  final Map<Uri, Uint8List> _dills;

  _FileSystem(this._channel, this._dills);

  @override
  fe.FileSystemEntity entityForUri(Uri uri) {
    return _FileSystemEntity(this, uri);
  }
}

class _FileSystemEntity implements fe.FileSystemEntity {
  final _FileSystem _fileSystem;

  @override
  final Uri uri;

  _FileSystemEntity(this._fileSystem, this.uri);

  RequestChannel get _channel => _fileSystem._channel;

  String get _uriStr => uri.toString();

  @override
  Future<bool> exists() async {
    if (_fileSystem._dills.containsKey(uri)) {
      return true;
    }
    return _channel.sendRequest<bool>('file.exists', _uriStr);
  }

  @override
  Future<bool> existsAsyncIfPossible() => exists();

  @override
  Future<List<int>> readAsBytes() async {
    final storedBytes = _fileSystem._dills[uri];
    if (storedBytes != null) {
      return storedBytes;
    }

    return _channel.sendRequest<Uint8List>('file.readAsBytes', _uriStr);
  }

  @override
  Future<List<int>> readAsBytesAsyncIfPossible() => readAsBytes();

  @override
  Future<String> readAsString() async {
    return _channel.sendRequest<String>('file.readAsString', _uriStr);
  }
}

class _ParsedAddress {
  final String host;
  final int port;

  factory _ParsedAddress.parse(String str) {
    final colonOffset = str.lastIndexOf(':');
    if (colonOffset == -1) {
      throw FormatException("Expected ':' in: $str");
    }

    return _ParsedAddress._(
      str.substring(0, colonOffset),
      int.parse(str.substring(colonOffset + 1)),
    );
  }

  _ParsedAddress._(this.host, this.port);
}

extension on Object? {
  Map<Object?, Object?> get argumentAsMap {
    final self = this;
    if (self is Map<Object?, Object?>) {
      return self;
    }
    throw ArgumentError('The argument must be a map.');
  }
}

extension on Map<Object?, Object?> {
  T? optional<T extends Object>(String name) {
    final value = this[name];
    if (value == null) {
      return null;
    }
    if (value is T) {
      return value;
    }
    throw ArgumentError('Must be null or $T: $name');
  }

  T required<T>(String name) {
    final value = this[name];
    if (value is T) {
      return value;
    }
    throw ArgumentError('Must be $T: $name');
  }
}

extension on Object? {
  List<T>? asListOf<T>() {
    final self = this;
    if (self is List<Object?>) {
      final result = <T>[];
      for (final element in self) {
        if (element is T) {
          result.add(element);
        } else {
          return null;
        }
      }
      return result;
    }
    return null;
  }
}
