// Copyright 2019 The Fuchsia Authors. 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:typed_data';

import 'package:meta/meta.dart';

import 'bitfield64.dart';
import 'heap.dart';
import 'util.dart';
import 'vmo_fields.dart';
import 'vmo_holder.dart';

/// Mirrors a single block in the VMO.
///
/// Can be read from VMO and/or initialized and modified by code, then
/// written to VMO if desired.
class Block {
  final _header = Bitfield64();
  final _payloadBits = Bitfield64();

  final VmoHolder _vmo;

  /// Index of the block within the VMO
  final int index;

  /// The VMO this Block lives inside.
  @visibleForTesting
  VmoHolder get vmo => _vmo;

  /// Initializes an empty [BlockType.reserved] block that isn't in the VMO yet.
  Block.create(this._vmo, this.index) {
    _header
      ..write(typeBits, BlockType.reserved.value)
      ..write(orderBits, defaultBlockOrder);
  }

  /// Create a block with arbitrary type.
  /// @nodoc
  @visibleForTesting
  Block.createWithType(this._vmo, this.index, BlockType type) {
    _header..write(typeBits, type.value)..write(orderBits, defaultBlockOrder);
  }

  /// Initializes by reading the block from the VMO.
  Block.read(this._vmo, this.index) {
    // TODO(CF-603): Validate index. More validating of parameters everywhere.
    _header.value = _vmo.readInt64(_offset);
    _payloadBits.value = _vmo.readInt64(_payloadOffset);
  }

  /// The block's payload as a string of bytes (for [BlockType.nameUtf8] or
  /// [BlockType.extent]).
  /// @nodoc
  @visibleForTesting
  ByteData get payloadBytes =>
      _vmo.read(_payloadOffset, size - headerSizeBytes);

  void _writeHeader() {
    _vmo.writeInt64(_offset, _header.value);
  }

  void _writePayloadBits() {
    _vmo.writeInt64(_payloadOffset, _payloadBits.value);
  }

  void _writeAllBits() {
    _writeHeader();
    _writePayloadBits();
  }

  void _writePayloadBytes(ByteData bytes) {
    _vmo.write(_payloadOffset, bytes);
  }

  /// Initializes (the one and only) [BlockType.header] block.
  void becomeHeader() {
    _header
      ..write(typeBits, BlockType.header.value)
      ..write(orderBits, 0)
      ..write(headerMagicBits, headerMagicNumber)
      ..write(headerVersionBits, headerVersionNumber);
    _payloadBits.value = 0;
    _writeAllBits();
  }

  /// Start a VMO update.
  ///
  /// Only valid for the [BlockType.header] block; otherwise throws
  /// [StateError].
  void lock() {
    _checkType(BlockType.header);
    _checkLocked(false);
    _payloadBits.value++;
    _vmo.writeInt64Direct(_payloadOffset, _payloadBits.value);
  }

  /// Finish a VMO update.
  /// Only valid for the [BlockType.header] block; otherwise throws
  /// [StateError].
  void unlock() {
    _checkType(BlockType.header);
    _checkLocked(true);
    _payloadBits.value++;
    _vmo.writeInt64Direct(_payloadOffset, _payloadBits.value);
  }

  /// Initializes the root [BlockType.nodeValue] block.
  ///
  /// Throws [StateError] if this block wasn't [BlockType.reserved].
  void becomeRoot() {
    _checkType(BlockType.reserved);
    becomeValue(parentIndex: rootParentIndex, nameIndex: rootNameIndex);
    _header.write(orderBits, 0);
    becomeNode();
    _writeAllBits();
  }

  /// Converts a [BlockType.anyValue] block to a [BlockType.nodeValue] block.
  ///
  /// Throws [StateError] if this block wasn't [BlockType.anyValue].
  void becomeNode() {
    _checkType(BlockType.anyValue);
    _header.write(typeBits, BlockType.nodeValue.value);
    _payloadBits.value = 0;
    _writeAllBits();
  }

  /// Child count of [BlockType.nodeValue] or [BlockType.tombstone] block.
  ///
  /// Throws [StateError] if this block isn't [BlockType.nodeValue]
  /// or [BlockType.tombstone].
  set childCount(int value) {
    _checkNodeOrTombstone();
    _payloadBits.value = value;
    _writePayloadBits();
  }

  /// Child count of [BlockType.nodeValue] or [BlockType.tombstone] block.
  ///
  /// Throws [StateError] if this block isn't [BlockType.nodeValue]
  /// or [BlockType.tombstone].
  int get childCount {
    _checkNodeOrTombstone();
    return _payloadBits.value;
  }

  /// Converts an anyValue block to a [BlockType.propertyValue] block.
  ///
  /// Throws [StateError] if this block wasn't [BlockType.anyValue].
  void becomeProperty() {
    _checkType(BlockType.anyValue);
    _header.write(typeBits, BlockType.propertyValue.value);
    _payloadBits
      ..write(propertyExtentIndexBits, 0)
      ..write(propertyTotalLengthBits, 0)
      ..write(propertyFlagsBits, 0);
    _writeAllBits();
  }

  /// Total Length field of a [BlockType.propertyValue] block.
  ///
  /// Throws [StateError] if this block isn't [BlockType.propertyValue].
  int get propertyTotalLength {
    _checkType(BlockType.propertyValue);
    return _payloadBits.read(propertyTotalLengthBits);
  }

  /// Total Length field of a [BlockType.propertyValue] block.
  ///
  /// Throws [StateError] if this block isn't [BlockType.propertyValue].
  set propertyTotalLength(int length) {
    _checkType(BlockType.propertyValue);
    _payloadBits.write(propertyTotalLengthBits, length);
    _writePayloadBits();
  }

  /// Extent Index field of a [BlockType.propertyValue] block.
  ///
  /// Throws [StateError] if this block isn't [BlockType.propertyValue].
  int get propertyExtentIndex {
    _checkType(BlockType.propertyValue);
    return _payloadBits.read(propertyExtentIndexBits);
  }

  /// Extent Index field of a [BlockType.propertyValue] block.
  ///
  /// Throws [StateError] if this block isn't [BlockType.propertyValue].
  set propertyExtentIndex(int index) {
    _checkType(BlockType.propertyValue);
    _payloadBits.write(propertyExtentIndexBits, index);
    _writePayloadBits();
  }

  /// Flags field of a [BlockType.propertyValue] block.
  ///
  /// Throws [StateError] if this block isn't [BlockType.propertyValue].
  int get propertyFlags {
    _checkType(BlockType.propertyValue);
    return _payloadBits.read(propertyFlagsBits);
  }

  /// Flags field of a [BlockType.propertyValue] block.
  ///
  /// Throws [StateError] if this block isn't [BlockType.propertyValue].
  set propertyFlags(int flags) {
    _checkType(BlockType.propertyValue);
    _payloadBits.write(propertyFlagsBits, flags);
    _writePayloadBits();
  }

  /// Converts a [BlockType.nodeValue] block to a [BlockType.tombstone] block.
  ///
  /// Throws [StateError] if this block wasn't [BlockType.nodeValue].
  void becomeTombstone() {
    _checkType(BlockType.nodeValue);
    _header.write(typeBits, BlockType.tombstone.value);
    _writeHeader();
  }

  /// Makes any block [BlockType.free].
  void becomeFree(int next) {
    var orderValue = _header.read(orderBits);
    _header
      ..value = 0
      ..write(orderBits, orderValue)
      ..write(typeBits, BlockType.free.value)
      ..write(nextFreeBits, next);
    _writeHeader();
  }

  /// Converts a [BlockType.free] to a [BlockType.reserved] block.
  ///
  /// Throws [StateError] if this block wasn't [BlockType.nodeValue].
  void becomeReserved() {
    _checkType(BlockType.free);
    _header.write(typeBits, BlockType.reserved.value);
    _writeHeader();
  }

  /// Index of next-free-block.
  ///
  /// Throws [StateError] if block isn't [BlockType.free].
  int get nextFree {
    _checkType(BlockType.free);
    return _header.read(nextFreeBits); // _header.read(nextFreeBits);
  }

  /// Initializes a value-holding block as [BlockType.anyValue].
  ///
  /// Does not write it, because [BlockType.anyValue] is not part of VMO format.
  /// This is a helper function called prior to [becomeNode()],
  /// [becomeProperty()], and [becomeMetric()].
  ///
  /// Throws [StateError] if block wasn't [BlockType.reserved].
  void becomeValue({@required int nameIndex, @required int parentIndex}) {
    _checkType(BlockType.reserved);
    _header
      ..write(typeBits, BlockType.anyValue.value)
      ..write(parentIndexBits, parentIndex)
      ..write(nameIndexBits, nameIndex);
    _writeHeader();
  }

  /// The index of the [BlockType.name] block of a *_VALUE block.
  ///
  /// Throws [StateError] if block isn't a value-holding block.
  int get nameIndex {
    _checkIsValue();
    return _header.read(nameIndexBits);
  }

  /// The index of the parent [BlockType.nodeValue] block of a *_VALUE block.
  ///
  /// Throws [StateError] if block isn't a value-holding block.
  int get parentIndex {
    _checkIsValue();
    return _header.read(parentIndexBits);
  }

  /// Converts a [BlockType.anyValue] block to a [BlockType.doubleValue] block,
  /// and sets starting [value].
  ///
  /// Throws [StateError] if block wasn't a [BlockType.anyValue] block.
  void becomeDoubleMetric(double value) {
    _checkType(BlockType.anyValue);
    _header.write(typeBits, BlockType.doubleValue.value);
    _payloadBits.value = _doubleBitsToInt(value);
    _writeAllBits();
  }

  /// Converts a [BlockType.anyValue] block to a [BlockType.intValue] block,
  /// and sets starting [value].
  ///
  /// Throws [StateError] if block wasn't a [BlockType.anyValue] block.
  void becomeIntMetric(int value) {
    _checkType(BlockType.anyValue);
    _header.write(typeBits, BlockType.intValue.value);
    _payloadBits.value = value;
    _writeAllBits();
  }

  /// Value payload stored in a [BlockType.intValue] block.
  ///
  /// Throws [StateError] if block isn't a [BlockType.intValue] block.
  int get intValue {
    _checkType(BlockType.intValue);
    return _payloadBits.value;
  }

  /// Writes int value payload to a [BlockType.intValue] block.
  ///
  /// Throws [StateError] if block isn't a [BlockType.intValue] block.
  set intValue(int value) {
    _checkType(BlockType.intValue);
    _payloadBits.value = value;
    _writePayloadBits();
  }

  /// Value payload stored in a [BlockType.doubleValue] block.
  ///
  /// Throws [StateError] if block isn't a [BlockType.doubleValue] block.
  double get doubleValue {
    _checkType(BlockType.doubleValue);
    return _intBitsToDouble(_payloadBits.value);
  }

  /// Write double value payload to a [BlockType.doubleValue] block.
  ///
  /// Throws [StateError] if block isn't a [BlockType.doubleValue] block.
  set doubleValue(double value) {
    _checkType(BlockType.doubleValue);
    _payloadBits.value = _doubleBitsToInt(value);
    _writePayloadBits();
  }

  /// Initializes a [BlockType.name] block.
  ///
  /// Throws [StateError] if block wasn't a [BlockType.reserved] block.
  void becomeName(String name) {
    _checkType(BlockType.reserved);
    var stringBytes = toByteData(name, maxBytes: payloadSpaceBytes);
    _header
      ..write(typeBits, BlockType.nameUtf8.value)
      ..write(nameLengthBits, stringBytes.lengthInBytes);
    _writeHeader();
    _writePayloadBytes(stringBytes);
  }

  /// Gets the utf8 name from a NAME block
  /// @nodoc
  @visibleForTesting
  ByteData get nameUtf8 {
    _checkType(BlockType.nameUtf8);
    return ByteData.view(payloadBytes.buffer, payloadBytes.offsetInBytes,
        _header.read(nameLengthBits));
  }

  /// Adds a [BlockType.reserved] block to the head of a [BlockType.extent]
  /// chain.
  ///
  /// Throws [StateError] if block wasn't a [BlockType.reserved] block.
  void becomeExtent(int nextExtent) {
    _checkType(BlockType.reserved);
    _header
      ..write(typeBits, BlockType.extent.value)
      ..write(nextExtentBits, nextExtent);
    _writeHeader();
  }

  /// Writes the [BlockType.extent]'s data.
  ///
  /// Throws [StateError] if block isn't a [BlockType.extent] block.
  void setExtentPayload(ByteData data) {
    _checkType(BlockType.extent);
    _writePayloadBytes(data);
  }

  /// The next [Block] in a [BlockType.extent] chain.
  ///
  /// Throws [StateError] if block isn't a [BlockType.extent] block.
  int get nextExtent {
    _checkType(BlockType.extent);
    return _header.read(nextExtentBits);
  }

  /// The number of bytes available for payload in this [BlockType.extent]
  /// [Block].
  int get payloadSpaceBytes {
    return size - headerSizeBytes;
  }

  /// The VMO-format-defined type of this [Block].
  BlockType get type => BlockType.values[_header.read(typeBits)];

  /// Size of the [Block] in bytes.
  int get size => 1 << (_header.read(orderBits) + 4);

  /// Verifies this [Block] has the expected type; throws [StateError] if not.
  void _checkType(BlockType blockType) {
    if (type != blockType) {
      throw StateError('Incorrect block type: '
          'expected $blockType, but found $type.');
    }
  }

  /// Throws [StateError] if [type] is not [BlockType.nodeValue] or
  /// [BlockType.tombstone].
  void _checkNodeOrTombstone() {
    if (type != BlockType.nodeValue && type != BlockType.tombstone) {
      throw StateError('Incorrect block type: '
          'expected node or tombstone, but found $type.');
    }
  }

  /// Throws [StateError] if [type] is not a *_VALUE block, i.e.
  /// [BlockType.nodeValue], [BlockType.anyValue], [BlockType.intValue],
  /// [BlockType.doubleValue], or [BlockType.propertyValue].
  void _checkIsValue() {
    if (type != BlockType.anyValue &&
        type != BlockType.nodeValue &&
        type != BlockType.propertyValue &&
        type != BlockType.intValue &&
        type != BlockType.doubleValue) {
      throw StateError('Value block expected; this block is $type.');
    }
  }

  /// This block (verified elsewhere to be the HEADER) "locks" the VMO during
  /// updates: if the payload value is odd, the VMO contents are in flux,
  /// and readers should retry.
  void _checkLocked(bool locked) {
    if ((_payloadBits.value & 1 == 1) != locked) {
      throw StateError('Lock state error; expected locked = $locked.');
    }
  }

  /// Converts 64 [bits] (supplied as int) to the [double] they really are.
  double _intBitsToDouble(int bits) {
    var scratchpad = ByteData(8)..setInt64(0, bits);
    return scratchpad.getFloat64(0);
  }

  /// Converts a [double] [value] to its 64-bit contents returned as [int].
  int _doubleBitsToInt(double value) {
    var scratchpad = ByteData(8)..setFloat64(0, value);
    return scratchpad.getInt64(0);
  }

  /// The byte offset of this [Block] in the VMO (calculated from its [index]).
  int get _offset => index * bytesPerIndex;

  /// The byte offset of this [Block]'s payload in the VMO.
  int get _payloadOffset => _offset + headerSizeBytes;
}
