// Copyright (c) 2023, 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';

import '../../source_map.dart';

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

// TODO(joshualitt): Now that we have an IR, we should consider switching to a
// visitor pattern.
class 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();

  /// Get the current offset in the serialized data.
  int get offset => _index;

  final SourceMapSerializer sourceMapSerializer = SourceMapSerializer();

  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(Uint8List 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);
  }

  static final ByteData _f32ByteData = ByteData(4);
  static final Uint8List _f32Uint8List = _f32ByteData.buffer.asUint8List();
  void writeF32(double value) {
    _f32ByteData.setFloat32(0, value, Endian.little);
    writeBytes(_f32Uint8List);
  }

  static final ByteData _f64ByteData = ByteData(8);
  static final Uint8List _f64Uint8List = _f64ByteData.buffer.asUint8List();
  void writeF64(double value) {
    _f64ByteData.setFloat64(0, value, Endian.little);
    writeBytes(_f64Uint8List);
  }

  void writeName(String name) {
    final 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 = const []]) {
    if (traceEnabled) debugTrace(chunk);
    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 Serializer) {
          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);
}
