// Copyright (c) 2020, 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:convert';
import 'dart:typed_data';

/// Puts a buffer in front of a [Sink<List<int>>].
class BufferedSink {
  static const int _SIZE = 128 * 1024;
  static const int _SAFE_LENGTH = _SIZE - 5;

  final BytesBuilder _builder = BytesBuilder(copy: false);

  Uint8List _buffer = Uint8List(_SIZE);
  int _length = 0;

  final Float64List _doubleBuffer = Float64List(1);
  late final Uint8List _doubleBufferUint8 = _doubleBuffer.buffer.asUint8List();

  BufferedSink();

  int get offset => _builder.length + _length;

  Uint8List takeBytes() {
    _builder.add(_buffer.sublist(0, _length));
    return _builder.takeBytes();
  }

  @pragma("vm:prefer-inline")
  void writeBool(bool value) {
    writeByte(value ? 1 : 0);
  }

  @pragma("vm:prefer-inline")
  void writeByte(int byte) {
    assert((byte & 0xFF) == byte);
    _addByte(byte);
  }

  void writeBytes(Uint8List bytes) {
    if (bytes.isEmpty) {
      return;
    }

    // Usually the bytes is short, and fits the current buffer.
    if (_length + bytes.length < _SIZE) {
      _buffer.setRange(_length, _length + bytes.length, bytes);
      _length += bytes.length;
      return;
    }

    // If the bytes is too long, add separate buffers.
    if (bytes.length >= _SIZE) {
      _builder.add(_buffer.sublist(0, _length));
      _builder.add(bytes);
      // Start a new buffer.
      _buffer = Uint8List(_SIZE);
      _length = 0;
      return;
    }

    // Copy as much as we can into the current buffer.
    _buffer.setRange(_length, _SIZE, bytes);
    _builder.add(_buffer);

    // Copy the remainder into a new buffer.
    var alreadyCopied = _SIZE - _length;
    var remainder = bytes.length - alreadyCopied;
    _buffer = Uint8List(_SIZE);
    _buffer.setRange(0, remainder, bytes, alreadyCopied);
    _length = remainder;
  }

  void writeDouble(double value) {
    _doubleBuffer[0] = value;
    _addByte4(
      _doubleBufferUint8[0],
      _doubleBufferUint8[1],
      _doubleBufferUint8[2],
      _doubleBufferUint8[3],
    );
    _addByte4(
      _doubleBufferUint8[4],
      _doubleBufferUint8[5],
      _doubleBufferUint8[6],
      _doubleBufferUint8[7],
    );
  }

  void writeEnum(Enum e) {
    writeByte(e.index);
  }

  void writeIf<T extends Object>(
    bool condition,
    void Function() ifTrue,
  ) {
    if (condition) {
      writeBool(true);
      ifTrue();
    } else {
      writeBool(false);
    }
  }

  void writeIfType<T extends Object>(
    Object? object,
    void Function(T t) ifTrue,
  ) {
    if (object is T) {
      writeBool(true);
      ifTrue(object);
    } else {
      writeBool(false);
    }
  }

  /// Writes [items], converts to [List] first.
  void writeIterable<T>(Iterable<T> items, void Function(T x) writeItem) {
    writeList(items.toList(), writeItem);
  }

  void writeList<T>(List<T> items, void Function(T x) writeItem) {
    writeUInt30(items.length);
    for (var i = 0; i < items.length; i++) {
      writeItem(items[i]);
    }
  }

  /// Write [items] filtering them by [T].
  void writeList2<T>(List<Object> items, void Function(T x) writeItem) {
    var typedItems = items.whereType<T>().toList();
    writeUInt30(typedItems.length);
    for (var i = 0; i < typedItems.length; i++) {
      writeItem(typedItems[i]);
    }
  }

  void writeMap<K, V>(
    Map<K, V> map, {
    required void Function(K key) writeKey,
    required void Function(V value) writeValue,
  }) {
    writeUInt30(map.length);
    for (var entry in map.entries) {
      writeKey(entry.key);
      writeValue(entry.value);
    }
  }

  void writeOptionalObject<T>(T? object, void Function(T x) write) {
    if (object != null) {
      writeBool(true);
      write(object);
    } else {
      writeBool(false);
    }
  }

  void writeOptionalStringUtf8(String? value) {
    if (value != null) {
      writeBool(true);
      writeStringUtf8(value);
    } else {
      writeBool(false);
    }
  }

  void writeOptionalUInt30(int? value) {
    if (value != null) {
      writeBool(true);
      writeUInt30(value);
    } else {
      writeBool(false);
    }
  }

  /// Write the [value] as UTF8 encoded byte array.
  void writeStringUtf8(String value) {
    var bytes = const Utf8Encoder().convert(value);
    writeUint8List(bytes);
  }

  void writeStringUtf8Iterable(Iterable<String> items) {
    writeUInt30(items.length);
    for (var item in items) {
      writeStringUtf8(item);
    }
  }

  @pragma("vm:prefer-inline")
  void writeUInt30(int value) {
    assert(value >= 0 && value >> 30 == 0);
    if (value < 0x80) {
      _addByte(value);
    } else if (value < 0x4000) {
      _addByte2((value >> 8) | 0x80, value & 0xFF);
    } else {
      _addByte4((value >> 24) | 0xC0, (value >> 16) & 0xFF, (value >> 8) & 0xFF,
          value & 0xFF);
    }
  }

  void writeUint30List(List<int> values) {
    var length = values.length;
    writeUInt30(length);
    for (var i = 0; i < length; i++) {
      writeUInt30(values[i]);
    }
  }

  void writeUInt32(int value) {
    _addByte4((value >> 24) & 0xFF, (value >> 16) & 0xFF, (value >> 8) & 0xFF,
        value & 0xFF);
  }

  void writeUint8List(Uint8List bytes) {
    writeUInt30(bytes.length);
    writeBytes(bytes);
  }

  void writeUri(Uri uri) {
    var uriStr = uri.toString();
    writeStringUtf8(uriStr);
  }

  @pragma("vm:prefer-inline")
  void _addByte(int byte) {
    _buffer[_length++] = byte;
    if (_length == _SIZE) {
      _builder.add(_buffer);
      _buffer = Uint8List(_SIZE);
      _length = 0;
    }
  }

  @pragma("vm:prefer-inline")
  void _addByte2(int byte1, int byte2) {
    if (_length < _SAFE_LENGTH) {
      _buffer[_length++] = byte1;
      _buffer[_length++] = byte2;
    } else {
      _addByte(byte1);
      _addByte(byte2);
    }
  }

  @pragma("vm:prefer-inline")
  void _addByte4(int byte1, int byte2, int byte3, int byte4) {
    if (_length < _SAFE_LENGTH) {
      _buffer[_length++] = byte1;
      _buffer[_length++] = byte2;
      _buffer[_length++] = byte3;
      _buffer[_length++] = byte4;
    } else {
      _addByte(byte1);
      _addByte(byte2);
      _addByte(byte3);
      _addByte(byte4);
    }
  }
}
