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

String paddedHex(int value, [int bytes = 0]) =>
    value.toRadixString(16).padLeft(2 * bytes, '0');

class Reader {
  final ByteData bdata;
  // These are mutable so we can update them, in case the endianness and
  // wordSize are read using the reader (e.g., ELF files).
  Endian? _endian;
  int? _wordSize;

  int _offset = 0;

  Endian get endian => _endian as Endian;
  set endian(Endian value) => _endian = value;
  int get wordSize => _wordSize as int;
  set wordSize(int value) => _wordSize = value;

  /// Unless provided, [wordSize] and [endian] are initialized to values that
  /// ensure no reads are made that depend on their value (e.g., readBytes).
  Reader.fromTypedData(TypedData data, {int? wordSize, Endian? endian})
      : _wordSize = wordSize,
        _endian = endian,
        bdata =
            ByteData.view(data.buffer, data.offsetInBytes, data.lengthInBytes);

  Reader.fromFile(String path, {int? wordSize, Endian? endian})
      : _wordSize = wordSize,
        _endian = endian,
        bdata = ByteData.sublistView(File(path).readAsBytesSync());

  /// Returns a reader focused on a different portion of the underlying buffer.
  /// If size is not provided, then the new reader extends to the end of the
  /// buffer.
  Reader refocusedCopy(int pos, [int? size]) {
    assert(pos >= 0 && pos < bdata.buffer.lengthInBytes);
    if (size != null) {
      assert(size >= 0 && (pos + size) <= bdata.buffer.lengthInBytes);
    } else {
      size = bdata.buffer.lengthInBytes - pos;
    }
    return Reader.fromTypedData(ByteData.view(bdata.buffer, pos, size),
        wordSize: _wordSize, endian: _endian);
  }

  int get start => bdata.offsetInBytes;
  int get offset => _offset;
  int get length => bdata.lengthInBytes;
  bool get done => _offset >= length;

  void seek(int offset, {bool absolute = false}) {
    final newOffset = (absolute ? 0 : _offset) + offset;
    assert(newOffset >= 0 && newOffset <= bdata.lengthInBytes);
    _offset = newOffset;
  }

  int readBytes(int size, {bool signed = false}) {
    if (_offset + size > length) {
      throw ArgumentError('attempt to read $size bytes with only '
          '${length - _offset} bytes remaining in the reader');
    }
    final start = _offset;
    _offset += size;
    switch (size) {
      case 1:
        return signed ? bdata.getInt8(start) : bdata.getUint8(start);
      case 2:
        return signed
            ? bdata.getInt16(start, endian)
            : bdata.getUint16(start, endian);
      case 4:
        return signed
            ? bdata.getInt32(start, endian)
            : bdata.getUint32(start, endian);
      case 8:
        return signed
            ? bdata.getInt64(start, endian)
            : bdata.getUint64(start, endian);
      default:
        _offset -= size;
        throw ArgumentError('invalid request to read $size bytes');
    }
  }

  int readByte({bool signed = false}) => readBytes(1, signed: signed);
  int readWord() => readBytes(wordSize);
  String readNullTerminatedString({int? maxSize}) {
    final start = _offset;
    int end = maxSize != null ? _offset + maxSize : bdata.lengthInBytes;
    for (; _offset < end; _offset++) {
      if (bdata.getUint8(_offset) == 0) {
        end = _offset;
        _offset++; // Move reader past null terminator.
        break;
      }
    }
    return String.fromCharCodes(
        bdata.buffer.asUint8List(bdata.offsetInBytes + start, end - start));
  }

  String readFixedLengthNullTerminatedString(int maxSize) {
    final start = _offset;
    final str = readNullTerminatedString(maxSize: maxSize);
    // Ensure reader points past fixed space, not at end of string within it.
    _offset = start + maxSize;
    return str;
  }

  int readLEB128EncodedInteger({bool signed = false}) {
    var ret = 0;
    var shift = 0;
    for (var byte = readByte(); !done; byte = readByte()) {
      ret |= (byte & 0x7f) << shift;
      shift += 7;
      if (byte & 0x80 == 0) {
        if (signed && byte & 0x40 != 0) {
          ret |= -(1 << shift);
        }
        break;
      }
    }
    return ret;
  }

  /// Repeatedly calls [callback] with this reader to retrieve items.
  ///
  /// The key of the returned [MapEntry]s are the offsets of the items. If
  /// absolute is false, the offsets are from the reader position when
  /// [readRepeated] was invoked, otherwise they are absolute offsets from
  /// the start of the reader.
  ///
  /// Stops either when the reader is empty or when a null item is returned
  /// from the callback.
  Iterable<MapEntry<int, S>> readRepeatedWithOffsets<S>(
      S? Function(Reader) callback,
      {bool absolute = false}) sync* {
    final start = offset;
    while (!done) {
      final itemStart = offset;
      final item = callback(this);
      if (item == null) break;
      yield MapEntry(absolute ? itemStart : itemStart - start, item);
    }
  }

  Iterable<S> readRepeated<S>(S? Function(Reader) callback) =>
      readRepeatedWithOffsets(callback).map((kv) => kv.value);

  void writeCurrentReaderPosition(StringBuffer buffer,
      {int maxSize = 0, int bytesPerLine = 16}) {
    var baseData = ByteData.view(bdata.buffer, 0, bdata.buffer.lengthInBytes);
    var startOffset = 0;
    var endOffset = baseData.lengthInBytes;
    final currentOffset = start + _offset;
    if (maxSize != 0 && maxSize < baseData.lengthInBytes) {
      var lowerWindow = currentOffset - (maxSize >> 1);
      // Adjust so that we always start at the beginning of a line.
      lowerWindow -= lowerWindow % bytesPerLine;
      final upperWindow = lowerWindow + maxSize;
      startOffset = max(startOffset, lowerWindow);
      endOffset = min(endOffset, upperWindow);
    }
    for (var i = startOffset; i < endOffset; i += bytesPerLine) {
      buffer
        ..write('0x')
        ..write(paddedHex(i, 8))
        ..write(' ');
      for (var j = 0; j < bytesPerLine && i + j < endOffset; j++) {
        var byte = baseData.getUint8(i + j);
        buffer
          ..write(i + j == currentOffset ? '|' : ' ')
          ..write(paddedHex(byte, 1));
      }
      buffer.writeln();
    }
  }

  @override
  String toString() {
    final buffer = StringBuffer();
    buffer
      ..write('Word size: ')
      ..write(_wordSize)
      ..writeln();
    buffer
      ..write('Endianness: ')
      ..write(_endian)
      ..writeln();
    buffer
      ..write('Start:  0x')
      ..write(paddedHex(start, _wordSize ?? 0))
      ..write(' (')
      ..write(start)
      ..writeln(')');
    buffer
      ..write('Offset: 0x')
      ..write(paddedHex(offset, _wordSize ?? 0))
      ..write(' (')
      ..write(offset)
      ..writeln(')');
    buffer
      ..write('Length: 0x')
      ..write(paddedHex(length, _wordSize ?? 0))
      ..write(' (')
      ..write(length)
      ..writeln(')');
    buffer.writeln('Bytes around current position:');
    writeCurrentReaderPosition(buffer, maxSize: 256);
    return buffer.toString();
  }
}
