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

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

import 'exceptions.dart';

class InvalidEncodingException extends InvalidHeadersException {
  InvalidEncodingException(String headers)
      : super('Encoding in supplied headers is not supported.', headers);
}

class InvalidHeadersException extends DebugAdapterException {
  InvalidHeadersException(String message, String headers)
      : super('$message\n\nHeaders:\n$headers');
}

/// Transforms a stream of LSP/DAP data in the form:
///
///     Content-Length: xxx\r\n
///     Content-Type: application/vscode-jsonrpc; charset=utf-8\r\n
///     \r\n
///     { JSON payload }
///
/// into just the JSON payload, decoded with the specified encoding. Line endings
/// for headers must be \r\n on all platforms as defined in the LSP spec.
class PacketTransformer extends StreamTransformerBase<List<int>, String> {
  @override
  Stream<String> bind(Stream<List<int>> stream) {
    late StreamSubscription<int> input;
    late StreamController<String> output;
    final buffer = <int>[];
    var isParsingHeaders = true;
    ProtocolHeaders? headers;
    output = StreamController<String>(
      onListen: () {
        input = stream.expand((b) => b).listen(
          (codeUnit) {
            buffer.add(codeUnit);
            try {
              if (isParsingHeaders && _endsWithCrLfCrLf(buffer)) {
                headers = _parseHeaders(buffer);
                buffer.clear();
                isParsingHeaders = false;
              } else if (!isParsingHeaders &&
                  buffer.length >= headers!.contentLength) {
                // UTF-8 is the default - and only supported - encoding for LSP.
                // The string 'utf8' is valid since it was published in the original spec.
                // Any other encodings should be rejected with an error.
                if ([null, 'utf-8', 'utf8']
                    .contains(headers?.encoding?.toLowerCase())) {
                  output.add(utf8.decode(buffer));
                } else {
                  output.addError(
                    InvalidEncodingException(headers!.rawHeaders),
                  );
                }
                buffer.clear();
                isParsingHeaders = true;
              }
            } on DebugAdapterException catch (e) {
              output.addError(e);
              output.close();
            }
          },
          onError: output.addError,
          onDone: output.close,
        );
      },
      onPause: () => input.pause(),
      onResume: () => input.resume(),
      onCancel: () => input.cancel(),
    );
    return output.stream;
  }

  /// Whether [buffer] ends in '\r\n\r\n'.
  static bool _endsWithCrLfCrLf(List<int> buffer) {
    var l = buffer.length;
    return l > 4 &&
        buffer[l - 1] == 10 &&
        buffer[l - 2] == 13 &&
        buffer[l - 3] == 10 &&
        buffer[l - 4] == 13;
  }

  static String? _extractEncoding(String header) {
    final charset = header
        .split(';')
        .map((s) => s.trim().toLowerCase())
        .firstWhere((s) => s.startsWith('charset='), orElse: () => '');

    return charset == '' ? null : charset.split('=')[1];
  }

  /// Decodes [buffer] into a String and returns the 'Content-Length' header value.
  static ProtocolHeaders _parseHeaders(List<int> buffer) {
    final String asString;
    try {
      // Headers are specified as always ASCII in LSP.
      asString = ascii.decode(buffer);
    } on FormatException {
      throw FormatException('Unable to decode headers with ascii. '
          'The stream has utf8 content:\n${utf8.decode(buffer)}');
    }
    final headers = asString.split('\r\n');
    final lengthHeader = headers.firstWhere(
        (h) => h.startsWith('Content-Length'),
        orElse: () => throw InvalidHeadersException(
            'No Content-Length header was supplied', asString));
    final length = lengthHeader.split(':').last.trim();
    final contentTypeHeader = headers
        .firstWhere((h) => h.startsWith('Content-Type'), orElse: () => '');
    final encoding = _extractEncoding(contentTypeHeader);
    return ProtocolHeaders(asString, int.parse(length), encoding);
  }
}

class ProtocolHeaders {
  final String rawHeaders;
  final int contentLength;
  final String? encoding;
  ProtocolHeaders(this.rawHeaders, this.contentLength, this.encoding);
}
