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

import 'dart:collection';
import 'dart:convert';
import 'dart:typed_data';

abstract class Serializer {
  void writeByte(int byte);
  void writeBytes(List<int> bytes);
  void writeSigned(int value);
  void writeUnsigned(int value);
  void writeF32(double value);
  void writeF64(double value);
  void writeName(String name);
  void write(Serializable object);
  void writeList(List<Serializable> objects);
  void writeData(Serializer chunk, [List<int>? watchPoints]);

  Uint8List get data;
}

abstract class Serializable {
  void serialize(Serializer s);
}

mixin SerializerMixin implements Serializer {
  static bool traceEnabled = false;

  // The prefix of `_data` up to `_index` contains the data serialized so far.
  Uint8List _data = Uint8List(24);
  int _index = 0;

  // Stack traces or other serializers attached to byte positions within the
  // chunk of data produced by this serializer.
  late final SplayTreeMap<int, Object> _traces = SplayTreeMap();

  void _ensure(int size) {
    // Ensure space for at least `size` additional bytes.
    if (_data.length < _index + size) {
      int newLength = _data.length * 2;
      while (newLength < _index + size) {
        newLength *= 2;
      }
      _data = Uint8List(newLength)..setRange(0, _data.length, _data);
    }
  }

  void _debugTrace(Object data) {
    _traces[_index] ??= data;
  }

  void writeByte(int byte) {
    if (traceEnabled) _debugTrace(StackTrace.current);
    assert(byte == byte & 0xFF);
    _ensure(1);
    _data[_index++] = byte;
  }

  void writeBytes(List<int> bytes) {
    if (traceEnabled) _debugTrace(StackTrace.current);
    _ensure(bytes.length);
    _data.setRange(_index, _index += bytes.length, bytes);
  }

  void writeSigned(int value) {
    while (value < -0x40 || value >= 0x40) {
      writeByte((value & 0x7F) | 0x80);
      value >>= 7;
    }
    writeByte(value & 0x7F);
  }

  void writeUnsigned(int value) {
    assert(value >= 0);
    while (value >= 0x80) {
      writeByte((value & 0x7F) | 0x80);
      value >>= 7;
    }
    writeByte(value);
  }

  void writeF32(double value) {
    // Get the binary representation of the F32.
    List<int> bytes = Float32List.fromList([value]).buffer.asUint8List();
    assert(bytes.length == 4);
    if (Endian.host == Endian.big) bytes = bytes.reversed.toList();
    writeBytes(bytes);
  }

  void writeF64(double value) {
    // Get the binary representation of the F64.
    List<int> bytes = Float64List.fromList([value]).buffer.asUint8List();
    assert(bytes.length == 8);
    if (Endian.host == Endian.big) bytes = bytes.reversed.toList();
    writeBytes(bytes);
  }

  void writeName(String name) {
    List<int> bytes = utf8.encode(name);
    writeUnsigned(bytes.length);
    writeBytes(bytes);
  }

  void write(Serializable object) {
    object.serialize(this);
  }

  void writeList(List<Serializable> objects) {
    writeUnsigned(objects.length);
    for (int i = 0; i < objects.length; i++) {
      write(objects[i]);
    }
  }

  void writeData(Serializer chunk, [List<int>? watchPoints]) {
    if (traceEnabled) _debugTrace(chunk);
    if (watchPoints != null) {
      for (int watchPoint in watchPoints) {
        if (_index <= watchPoint && watchPoint < _index + chunk.data.length) {
          int byteValue = chunk.data[watchPoint - _index];
          Object trace = this;
          int offset = watchPoint;
          while (trace is SerializerMixin) {
            int keyOffset = trace._traces.containsKey(offset)
                ? offset
                : trace._traces.lastKeyBefore(offset)!;
            trace = trace._traces[keyOffset]!;
            offset -= keyOffset;
          }
          String byte = byteValue.toRadixString(16).padLeft(2, '0');
          print("Watch $watchPoint: 0x$byte\n$trace");
        }
      }
    }
    writeBytes(chunk.data);
  }

  Uint8List get data => Uint8List.sublistView(_data, 0, _index);
}
