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

  /// 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.
  @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]).
  @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
  @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;
}
