import { fromByteWidth } from './bit-width-util'
import { ValueType } from './value-type'
import { isNumber, isIndirectNumber, isAVector, fixedTypedVectorElementSize, isFixedTypedVector, isTypedVector, typedVectorElementType, packedType, fixedTypedVectorElementType } from './value-type-util'
import { indirect, keyForIndex, keyIndex, readFloat, readInt, readUInt, valueForIndexWithKey } from './reference-util'
import { Long } from '../long';
import { fromUTF8Array } from './flexbuffers-util';
import { BitWidth } from './bit-width';

export function toReference(buffer: Uint8Array): Reference {
  const len = buffer.byteLength;
  
  if (len < 3) {
    throw "Buffer needs to be bigger than 3";
  }

  const dataView = new DataView(buffer);
  const byteWidth = dataView.getUint8(len - 1);
  const packedType = dataView.getUint8(len - 2);
  const parentWidth = fromByteWidth(byteWidth);
  const offset = len - byteWidth - 2;

  return new Reference(dataView, offset, parentWidth, packedType, "/")
}

export class Reference {
  private readonly byteWidth: number
  private readonly valueType: ValueType
  private _length = -1
  constructor(private dataView: DataView, private offset: number, private parentWidth: number, private packedType: ValueType, private path: string) {
    this.byteWidth = 1 << (packedType & 3)
    this.valueType = packedType >> 2
  }

  isNull(): boolean { return this.valueType === ValueType.NULL; }
  isNumber(): boolean { return isNumber(this.valueType) || isIndirectNumber(this.valueType); }
  isFloat(): boolean { return ValueType.FLOAT === this.valueType || ValueType.INDIRECT_FLOAT === this.valueType; }
  isInt(): boolean { return this.isNumber() && !this.isFloat(); }
  isString(): boolean { return ValueType.STRING === this.valueType || ValueType.KEY === this.valueType; }
  isBool(): boolean { return ValueType.BOOL === this.valueType; }
  isBlob(): boolean { return ValueType.BLOB === this.valueType; }
  isVector(): boolean { return isAVector(this.valueType); }
  isMap(): boolean { return ValueType.MAP === this.valueType; }

  boolValue(): boolean | null {
    if (this.isBool()) {
      return readInt(this.dataView, this.offset, this.parentWidth) > 0;
    }
    return null;
  }

  intValue(): number | Long | bigint | null {
    if (this.valueType === ValueType.INT) {
      return readInt(this.dataView, this.offset, this.parentWidth);
    }
    if (this.valueType === ValueType.UINT) {
      return readUInt(this.dataView, this.offset, this.parentWidth);
    }
    if (this.valueType === ValueType.INDIRECT_INT) {
      return readInt(this.dataView, indirect(this.dataView, this.offset, this.parentWidth), fromByteWidth(this.byteWidth));
    }
    if (this.valueType === ValueType.INDIRECT_UINT) {
      return readUInt(this.dataView, indirect(this.dataView, this.offset, this.parentWidth), fromByteWidth(this.byteWidth));
    }
    return null;
  }

  floatValue(): number | null {
    if (this.valueType === ValueType.FLOAT) {
      return readFloat(this.dataView, this.offset, this.parentWidth);
    }
    if (this.valueType === ValueType.INDIRECT_FLOAT) {
      return readFloat(this.dataView, indirect(this.dataView, this.offset, this.parentWidth), fromByteWidth(this.byteWidth));
    }
    return null;
  }

  numericValue(): number | Long | bigint | null { return this.floatValue() || this.intValue()}

  stringValue(): string | null {
    if (this.valueType === ValueType.STRING || this.valueType === ValueType.KEY) {
      const begin = indirect(this.dataView, this.offset, this.parentWidth);
      return fromUTF8Array(new Uint8Array(this.dataView.buffer, begin, this.length()));
    }
    return null;
  }

  blobValue(): Uint8Array | null {
    if (this.isBlob()) {
      const begin = indirect(this.dataView, this.offset, this.parentWidth);
      return new Uint8Array(this.dataView.buffer, begin, this.length());
    }
    return null;
  }

  get(key: number): Reference {
    const length = this.length();
    if (Number.isInteger(key) && isAVector(this.valueType)) {
      if (key >= length || key < 0) {
        throw `Key: [${key}] is not applicable on ${this.path} of ${this.valueType} length: ${length}`;
      }
      const _indirect = indirect(this.dataView, this.offset, this.parentWidth);
      const elementOffset = _indirect + key * this.byteWidth;
      let _packedType = this.dataView.getUint8(_indirect + length * this.byteWidth + key);
      if (isTypedVector(this.valueType)) {
        const _valueType = typedVectorElementType(this.valueType);
        _packedType = packedType(_valueType, BitWidth.WIDTH8);
      } else if (isFixedTypedVector(this.valueType)) {
        const _valueType = fixedTypedVectorElementType(this.valueType);
        _packedType = packedType(_valueType, BitWidth.WIDTH8);
      }
      return new Reference(this.dataView, elementOffset, fromByteWidth(this.byteWidth), _packedType, `${this.path}[${key}]`);
    }
    if (typeof key === 'string') {
      const index = keyIndex(key, this.dataView, this.offset, this.parentWidth, this.byteWidth, length);
      if (index !== null) {
        return valueForIndexWithKey(index, key, this.dataView, this.offset, this.parentWidth, this.byteWidth, length, this.path)
      }
    }
    throw `Key [${key}] is not applicable on ${this.path} of ${this.valueType}`;
  }

  length(): number {
    let size;
    if (this._length > -1) {
      return this._length;
    }
    if (isFixedTypedVector(this.valueType)) {
      this._length = fixedTypedVectorElementSize(this.valueType);
    } else if (this.valueType === ValueType.BLOB
      || this.valueType === ValueType.MAP
      || isAVector(this.valueType)) {
      this._length = readUInt(this.dataView, indirect(this.dataView, this.offset, this.parentWidth) - this.byteWidth, fromByteWidth(this.byteWidth)) as number
    } else if (this.valueType === ValueType.NULL) {
      this._length = 0;
    } else if (this.valueType === ValueType.STRING) {
      const _indirect = indirect(this.dataView, this.offset, this.parentWidth);
      let sizeByteWidth = this.byteWidth;
      size = readUInt(this.dataView, _indirect - sizeByteWidth, fromByteWidth(this.byteWidth));
      while (this.dataView.getInt8(_indirect + (size as number)) !== 0) {
        sizeByteWidth <<= 1;
        size = readUInt(this.dataView, _indirect - sizeByteWidth, fromByteWidth(this.byteWidth));
      }
      this._length = size as number;
    } else if (this.valueType === ValueType.KEY) {
      const _indirect = indirect(this.dataView, this.offset, this.parentWidth);
      size = 1;
      while (this.dataView.getInt8(_indirect + size) !== 0) {
        size++;
      }
      this._length = size;
    } else {
      this._length = 1;
    }
    return this._length;
  }

  toObject(): unknown {
    const length = this.length();
    if (this.isVector()) {
      const result = [];
      for (let i = 0; i < length; i++) {
        result.push(this.get(i).toObject());
      }
      return result;
    }
    if (this.isMap()) {
      const result: Record<string, unknown> = {};
      for (let i = 0; i < length; i++) {
        const key = keyForIndex(i, this.dataView, this.offset, this.parentWidth, this.byteWidth);
        result[key] = valueForIndexWithKey(i, key, this.dataView, this.offset, this.parentWidth, this.byteWidth, length, this.path).toObject();
      }
      return result;
    }
    if (this.isNull()) {
      return null;
    }
    if (this.isBool()) {
      return this.boolValue();
    }
    if (this.isNumber()) {
      return this.numericValue();
    }
    return this.blobValue() || this.stringValue();
  }
}
