import { isHighSurrogate } from "../../../base/common/strings.mjs";
import { isLittleEndian } from "../../../base/common/platform.mjs";
import { readUInt16LE } from "../../../base/common/buffer.mjs";
let _utf16LE_TextDecoder;
function getUTF16LE_TextDecoder() {
  if (!_utf16LE_TextDecoder) {
    _utf16LE_TextDecoder = new TextDecoder("UTF-16LE");
  }
  return _utf16LE_TextDecoder;
}
let _utf16BE_TextDecoder;
function getUTF16BE_TextDecoder() {
  if (!_utf16BE_TextDecoder) {
    _utf16BE_TextDecoder = new TextDecoder("UTF-16BE");
  }
  return _utf16BE_TextDecoder;
}
let _platformTextDecoder;
function getPlatformTextDecoder() {
  if (!_platformTextDecoder) {
    _platformTextDecoder = isLittleEndian() ? getUTF16LE_TextDecoder() : getUTF16BE_TextDecoder();
  }
  return _platformTextDecoder;
}
const hasTextDecoder = typeof TextDecoder !== "undefined";
let createStringBuilder;
let decodeUTF16LE;
if (hasTextDecoder) {
  createStringBuilder = (capacity) => new StringBuilder(capacity);
  decodeUTF16LE = standardDecodeUTF16LE;
} else {
  createStringBuilder = (capacity) => new CompatStringBuilder();
  decodeUTF16LE = compatDecodeUTF16LE;
}
function standardDecodeUTF16LE(source, offset, len) {
  const view = new Uint16Array(source.buffer, offset, len);
  if (len > 0 && (view[0] === 65279 || view[0] === 65534)) {
    return compatDecodeUTF16LE(source, offset, len);
  }
  return getUTF16LE_TextDecoder().decode(view);
}
function compatDecodeUTF16LE(source, offset, len) {
  const result = [];
  let resultLen = 0;
  for (let i = 0; i < len; i++) {
    const charCode = readUInt16LE(source, offset);
    offset += 2;
    result[resultLen++] = String.fromCharCode(charCode);
  }
  return result.join("");
}
class StringBuilder {
  constructor(capacity) {
    this._capacity = capacity | 0;
    this._buffer = new Uint16Array(this._capacity);
    this._completedStrings = null;
    this._bufferLength = 0;
  }
  reset() {
    this._completedStrings = null;
    this._bufferLength = 0;
  }
  build() {
    if (this._completedStrings !== null) {
      this._flushBuffer();
      return this._completedStrings.join("");
    }
    return this._buildBuffer();
  }
  _buildBuffer() {
    if (this._bufferLength === 0) {
      return "";
    }
    const view = new Uint16Array(this._buffer.buffer, 0, this._bufferLength);
    return getPlatformTextDecoder().decode(view);
  }
  _flushBuffer() {
    const bufferString = this._buildBuffer();
    this._bufferLength = 0;
    if (this._completedStrings === null) {
      this._completedStrings = [bufferString];
    } else {
      this._completedStrings[this._completedStrings.length] = bufferString;
    }
  }
  write1(charCode) {
    const remainingSpace = this._capacity - this._bufferLength;
    if (remainingSpace <= 1) {
      if (remainingSpace === 0 || isHighSurrogate(charCode)) {
        this._flushBuffer();
      }
    }
    this._buffer[this._bufferLength++] = charCode;
  }
  appendASCII(charCode) {
    if (this._bufferLength === this._capacity) {
      this._flushBuffer();
    }
    this._buffer[this._bufferLength++] = charCode;
  }
  appendASCIIString(str) {
    const strLen = str.length;
    if (this._bufferLength + strLen >= this._capacity) {
      this._flushBuffer();
      this._completedStrings[this._completedStrings.length] = str;
      return;
    }
    for (let i = 0; i < strLen; i++) {
      this._buffer[this._bufferLength++] = str.charCodeAt(i);
    }
  }
}
class CompatStringBuilder {
  constructor() {
    this._pieces = [];
    this._piecesLen = 0;
  }
  reset() {
    this._pieces = [];
    this._piecesLen = 0;
  }
  build() {
    return this._pieces.join("");
  }
  write1(charCode) {
    this._pieces[this._piecesLen++] = String.fromCharCode(charCode);
  }
  appendASCII(charCode) {
    this._pieces[this._piecesLen++] = String.fromCharCode(charCode);
  }
  appendASCIIString(str) {
    this._pieces[this._piecesLen++] = str;
  }
}
export {
  createStringBuilder,
  decodeUTF16LE,
  getPlatformTextDecoder,
  hasTextDecoder
};
