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

/// Main class to read a value out of a FlexBuffer.
///
/// This class let you access values stored in the buffer in a lazy fashion.
class Reference {
  final ByteData _buffer;
  final int _offset;
  final BitWidth _parentWidth;
  final String _path;
  final int _byteWidth;
  final ValueType _valueType;
  int? _length;

  Reference._(
      this._buffer, this._offset, this._parentWidth, int packedType, this._path,
      [int? byteWidth, ValueType? valueType])
      : _byteWidth = byteWidth ?? 1 << (packedType & 3),
        _valueType = valueType ?? ValueTypeUtils.fromInt(packedType >> 2);

  /// Use this method to access the root value of a FlexBuffer.
  static Reference fromBuffer(ByteBuffer buffer) {
    final len = buffer.lengthInBytes;
    if (len < 3) {
      throw UnsupportedError('Buffer needs to be bigger than 3');
    }
    final byteData = ByteData.view(buffer);
    final byteWidth = byteData.getUint8(len - 1);
    final packedType = byteData.getUint8(len - 2);
    final offset = len - byteWidth - 2;
    return Reference._(ByteData.view(buffer), offset,
        BitWidthUtil.fromByteWidth(byteWidth), packedType, "/");
  }

  /// Returns true if the underlying value is null.
  bool get isNull => _valueType == ValueType.Null;

  /// Returns true if the underlying value can be represented as [num].
  bool get isNum =>
      ValueTypeUtils.isNumber(_valueType) ||
      ValueTypeUtils.isIndirectNumber(_valueType);

  /// Returns true if the underlying value was encoded as a float (direct or indirect).
  bool get isDouble =>
      _valueType == ValueType.Float || _valueType == ValueType.IndirectFloat;

  /// Returns true if the underlying value was encoded as an int or uint (direct or indirect).
  bool get isInt => isNum && !isDouble;

  /// Returns true if the underlying value was encoded as a string or a key.
  bool get isString =>
      _valueType == ValueType.String || _valueType == ValueType.Key;

  /// Returns true if the underlying value was encoded as a bool.
  bool get isBool => _valueType == ValueType.Bool;

  /// Returns true if the underlying value was encoded as a blob.
  bool get isBlob => _valueType == ValueType.Blob;

  /// Returns true if the underlying value points to a vector.
  bool get isVector => ValueTypeUtils.isAVector(_valueType);

  /// Returns true if the underlying value points to a map.
  bool get isMap => _valueType == ValueType.Map;

  /// If this [isBool], returns the bool value. Otherwise, returns null.
  bool? get boolValue {
    if (_valueType == ValueType.Bool) {
      return _readInt(_offset, _parentWidth) != 0;
    }
    return null;
  }

  /// Returns an [int], if the underlying value can be represented as an int.
  ///
  /// Otherwise returns [null].
  int? get intValue {
    if (_valueType == ValueType.Int) {
      return _readInt(_offset, _parentWidth);
    }
    if (_valueType == ValueType.UInt) {
      return _readUInt(_offset, _parentWidth);
    }
    if (_valueType == ValueType.IndirectInt) {
      return _readInt(_indirect, BitWidthUtil.fromByteWidth(_byteWidth));
    }
    if (_valueType == ValueType.IndirectUInt) {
      return _readUInt(_indirect, BitWidthUtil.fromByteWidth(_byteWidth));
    }
    return null;
  }

  /// Returns [double], if the underlying value [isDouble].
  ///
  /// Otherwise returns [null].
  double? get doubleValue {
    if (_valueType == ValueType.Float) {
      return _readFloat(_offset, _parentWidth);
    }
    if (_valueType == ValueType.IndirectFloat) {
      return _readFloat(_indirect, BitWidthUtil.fromByteWidth(_byteWidth));
    }
    return null;
  }

  /// Returns [num], if the underlying value is numeric, be it int uint, or float (direct or indirect).
  ///
  /// Otherwise returns [null].
  num? get numValue => doubleValue ?? intValue;

  /// Returns [String] value or null otherwise.
  ///
  /// This method performers a utf8 decoding, as FlexBuffers format stores strings in utf8 encoding.
  String? get stringValue {
    if (_valueType == ValueType.String || _valueType == ValueType.Key) {
      return utf8.decode(_buffer.buffer.asUint8List(_indirect, length));
    }
    return null;
  }

  /// Returns [Uint8List] value or null otherwise.
  Uint8List? get blobValue {
    if (_valueType == ValueType.Blob) {
      return _buffer.buffer.asUint8List(_indirect, length);
    }
    return null;
  }

  /// Can be used with an [int] or a [String] value for key.
  /// If the underlying value in FlexBuffer is a vector, then use [int] for access.
  /// If the underlying value in FlexBuffer is a map, then use [String] for access.
  /// Returns [Reference] value. Throws an exception when [key] is not applicable.
  Reference operator [](Object key) {
    if (key is int && ValueTypeUtils.isAVector(_valueType)) {
      final index = key;
      if (index >= length || index < 0) {
        throw ArgumentError(
            'Key: [$key] is not applicable on: $_path of: $_valueType length: $length');
      }
      final elementOffset = _indirect + index * _byteWidth;
      int packedType = 0;
      int? byteWidth;
      ValueType? valueType;
      if (ValueTypeUtils.isTypedVector(_valueType)) {
        byteWidth = 1;
        valueType = ValueTypeUtils.typedVectorElementType(_valueType);
      } else if (ValueTypeUtils.isFixedTypedVector(_valueType)) {
        byteWidth = 1;
        valueType = ValueTypeUtils.fixedTypedVectorElementType(_valueType);
      } else {
        packedType = _buffer.getUint8(_indirect + length * _byteWidth + index);
      }
      return Reference._(
          _buffer,
          elementOffset,
          BitWidthUtil.fromByteWidth(_byteWidth),
          packedType,
          "$_path[$index]",
          byteWidth,
          valueType);
    }
    if (key is String && _valueType == ValueType.Map) {
      final index = _keyIndex(key);
      if (index != null) {
        return _valueForIndexWithKey(index, key);
      }
    }
    throw ArgumentError(
        'Key: [$key] is not applicable on: $_path of: $_valueType');
  }

  /// Get an iterable if the underlying flexBuffer value is a vector.
  /// Otherwise throws an exception.
  Iterable<Reference> get vectorIterable {
    if (isVector == false) {
      throw UnsupportedError('Value is not a vector. It is: $_valueType');
    }
    return _VectorIterator(this);
  }

  /// Get an iterable for keys if the underlying flexBuffer value is a map.
  /// Otherwise throws an exception.
  Iterable<String> get mapKeyIterable {
    if (isMap == false) {
      throw UnsupportedError('Value is not a map. It is: $_valueType');
    }
    return _MapKeyIterator(this);
  }

  /// Get an iterable for values if the underlying flexBuffer value is a map.
  /// Otherwise throws an exception.
  Iterable<Reference> get mapValueIterable {
    if (isMap == false) {
      throw UnsupportedError('Value is not a map. It is: $_valueType');
    }
    return _MapValueIterator(this);
  }

  /// Returns the length of the the underlying FlexBuffer value.
  /// If the underlying value is [null] the length is 0.
  /// If the underlying value is a number, or a bool, the length is 1.
  /// If the underlying value is a vector, or map, the length reflects number of elements / element pairs.
  /// If the values is a string or a blob, the length reflects a number of bytes the value occupies (strings are encoded in utf8 format).
  int get length {
    if (_length == null) {
      // needs to be checked before more generic isAVector
      if (ValueTypeUtils.isFixedTypedVector(_valueType)) {
        _length = ValueTypeUtils.fixedTypedVectorElementSize(_valueType);
      } else if (_valueType == ValueType.Blob ||
          ValueTypeUtils.isAVector(_valueType) ||
          _valueType == ValueType.Map) {
        _length = _readUInt(
            _indirect - _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
      } else if (_valueType == ValueType.Null) {
        _length = 0;
      } else if (_valueType == ValueType.String) {
        final indirect = _indirect;
        var sizeByteWidth = _byteWidth;
        var size = _readUInt(indirect - sizeByteWidth,
            BitWidthUtil.fromByteWidth(sizeByteWidth));
        while (_buffer.getInt8(indirect + size) != 0) {
          sizeByteWidth <<= 1;
          size = _readUInt(indirect - sizeByteWidth,
              BitWidthUtil.fromByteWidth(sizeByteWidth));
        }
        _length = size;
      } else if (_valueType == ValueType.Key) {
        final indirect = _indirect;
        var size = 1;
        while (_buffer.getInt8(indirect + size) != 0) {
          size += 1;
        }
        _length = size;
      } else {
        _length = 1;
      }
    }
    return _length!;
  }

  /// Returns a minified JSON representation of the underlying FlexBuffer value.
  ///
  /// This method involves materializing the entire object tree, which may be
  /// expensive. It is more efficient to work with [Reference] and access only the needed data.
  /// Blob values are represented as base64 encoded string.
  String get json {
    if (_valueType == ValueType.Bool) {
      return boolValue! ? 'true' : 'false';
    }
    if (_valueType == ValueType.Null) {
      return 'null';
    }
    if (ValueTypeUtils.isNumber(_valueType)) {
      return jsonEncode(numValue);
    }
    if (_valueType == ValueType.String) {
      return jsonEncode(stringValue);
    }
    if (_valueType == ValueType.Blob) {
      return jsonEncode(base64Encode(blobValue!));
    }
    if (ValueTypeUtils.isAVector(_valueType)) {
      final result = StringBuffer();
      result.write('[');
      for (var i = 0; i < length; i++) {
        result.write(this[i].json);
        if (i < length - 1) {
          result.write(',');
        }
      }
      result.write(']');
      return result.toString();
    }
    if (_valueType == ValueType.Map) {
      final result = StringBuffer();
      result.write('{');
      for (var i = 0; i < length; i++) {
        result.write(jsonEncode(_keyForIndex(i)));
        result.write(':');
        result.write(_valueForIndex(i).json);
        if (i < length - 1) {
          result.write(',');
        }
      }
      result.write('}');
      return result.toString();
    }
    throw UnsupportedError(
        'Type: $_valueType is not supported for JSON conversion');
  }

  /// Computes the indirect offset of the value.
  ///
  /// To optimize for the more common case of being called only once, this
  /// value is not cached. Callers that need to use it more than once should
  /// cache the return value in a local variable.
  int get _indirect {
    final step = _readUInt(_offset, _parentWidth);
    return _offset - step;
  }

  int _readInt(int offset, BitWidth width) {
    _validateOffset(offset, width);
    if (width == BitWidth.width8) {
      return _buffer.getInt8(offset);
    }
    if (width == BitWidth.width16) {
      return _buffer.getInt16(offset, Endian.little);
    }
    if (width == BitWidth.width32) {
      return _buffer.getInt32(offset, Endian.little);
    }
    return _buffer.getInt64(offset, Endian.little);
  }

  int _readUInt(int offset, BitWidth width) {
    _validateOffset(offset, width);
    if (width == BitWidth.width8) {
      return _buffer.getUint8(offset);
    }
    if (width == BitWidth.width16) {
      return _buffer.getUint16(offset, Endian.little);
    }
    if (width == BitWidth.width32) {
      return _buffer.getUint32(offset, Endian.little);
    }
    return _buffer.getUint64(offset, Endian.little);
  }

  double _readFloat(int offset, BitWidth width) {
    _validateOffset(offset, width);
    if (width.index < BitWidth.width32.index) {
      throw StateError('Bad width: $width');
    }

    if (width == BitWidth.width32) {
      return _buffer.getFloat32(offset, Endian.little);
    }

    return _buffer.getFloat64(offset, Endian.little);
  }

  void _validateOffset(int offset, BitWidth width) {
    if (_offset < 0 ||
        _buffer.lengthInBytes <= offset + width.index ||
        offset & (BitWidthUtil.toByteWidth(width) - 1) != 0) {
      throw StateError('Bad offset: $offset, width: $width');
    }
  }

  int? _keyIndex(String key) {
    final input = utf8.encode(key);
    final keysVectorOffset = _indirect - _byteWidth * 3;
    final indirectOffset = keysVectorOffset -
        _readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth));
    final byteWidth = _readUInt(
        keysVectorOffset + _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
    var low = 0;
    var high = length - 1;
    while (low <= high) {
      final mid = (high + low) >> 1;
      final dif = _diffKeys(input, mid, indirectOffset, byteWidth);
      if (dif == 0) return mid;
      if (dif < 0) {
        high = mid - 1;
      } else {
        low = mid + 1;
      }
    }
    return null;
  }

  int _diffKeys(List<int> input, int index, int indirectOffset, int byteWidth) {
    final keyOffset = indirectOffset + index * byteWidth;
    final keyIndirectOffset =
        keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth));
    for (var i = 0; i < input.length; i++) {
      final dif = input[i] - _buffer.getUint8(keyIndirectOffset + i);
      if (dif != 0) {
        return dif;
      }
    }
    return (_buffer.getUint8(keyIndirectOffset + input.length) == 0) ? 0 : -1;
  }

  Reference _valueForIndexWithKey(int index, String key) {
    final indirect = _indirect;
    final elementOffset = indirect + index * _byteWidth;
    final packedType = _buffer.getUint8(indirect + length * _byteWidth + index);
    return Reference._(_buffer, elementOffset,
        BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path/$key");
  }

  Reference _valueForIndex(int index) {
    final indirect = _indirect;
    final elementOffset = indirect + index * _byteWidth;
    final packedType = _buffer.getUint8(indirect + length * _byteWidth + index);
    return Reference._(_buffer, elementOffset,
        BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path/[$index]");
  }

  String _keyForIndex(int index) {
    final keysVectorOffset = _indirect - _byteWidth * 3;
    final indirectOffset = keysVectorOffset -
        _readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth));
    final byteWidth = _readUInt(
        keysVectorOffset + _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
    final keyOffset = indirectOffset + index * byteWidth;
    final keyIndirectOffset =
        keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth));
    var length = 0;
    while (_buffer.getUint8(keyIndirectOffset + length) != 0) {
      length += 1;
    }
    return utf8.decode(_buffer.buffer.asUint8List(keyIndirectOffset, length));
  }
}

class _VectorIterator
    with IterableMixin<Reference>
    implements Iterator<Reference> {
  final Reference _vector;
  int index = -1;

  _VectorIterator(this._vector);

  @override
  Reference get current => _vector[index];

  @override
  bool moveNext() {
    index++;
    return index < _vector.length;
  }

  @override
  Iterator<Reference> get iterator => this;
}

class _MapKeyIterator with IterableMixin<String> implements Iterator<String> {
  final Reference _map;
  int index = -1;

  _MapKeyIterator(this._map);

  @override
  String get current => _map._keyForIndex(index);

  @override
  bool moveNext() {
    index++;
    return index < _map.length;
  }

  @override
  Iterator<String> get iterator => this;
}

class _MapValueIterator
    with IterableMixin<Reference>
    implements Iterator<Reference> {
  final Reference _map;
  int index = -1;

  _MapValueIterator(this._map);

  @override
  Reference get current => _map._valueForIndex(index);

  @override
  bool moveNext() {
    index++;
    return index < _map.length;
  }

  @override
  Iterator<Reference> get iterator => this;
}
