/**
 * UnknownFields.ets
 *
 * 未知字段存储 - SwiftProtobuf 兼容性设计
 *
 * 用途:
 * 1. 前后兼容性 - 旧客户端接收新服务器的消息时,保留未知字段
 * 2. 消息转发 - 中间服务器不需要理解所有字段也能转发消息
 * 3. 版本演进 - 允许 proto 定义向前兼容
 *
 * 设计理念:
 * - 存储原始二进制数据(不解析)
 * - 在序列化时追加到消息末尾
 * - 零拷贝设计,高效内存使用
 *
 * Version: 1.0.0
 * ArkTS 2025 兼容
 */

/**
 * 未知字段存储类
 *
 * 当解码消息时遇到未知的字段编号(field number),
 * 会将该字段的原始二进制数据保存在此对象中。
 * 重新编码消息时,这些未知字段会被追加到消息末尾。
 *
 * 示例场景:
 * 1. 服务器升级了 proto 定义,新增了字段 3
 * 2. 旧客户端(只认识字段 1, 2)接收到消息
 * 3. 字段 3 的数据被保存到 unknownFields
 * 4. 客户端转发消息时,字段 3 的数据被完整保留
 */
export class UnknownFields {
  /**
   * 原始二进制数据
   *
   * ArkTS 注意:使用 Uint8Array 而不是 Buffer
   */
  private data: Uint8Array

  /**
   * 构造函数
   */
  constructor() {
    this.data = new Uint8Array(0)
  }

  /**
   * 追加未知字段数据
   *
   * @param bytes 要追加的二进制数据
   *
   * 注意:此方法会创建新的 Uint8Array,
   * 在频繁调用时可能有性能开销。
   */
  append(bytes: Uint8Array): void {
    if (bytes.length === 0) {
      return
    }

    // 创建新数组,容量为现有数据 + 新数据
    const newData = new Uint8Array(this.data.length + bytes.length)

    // 复制现有数据
    newData.set(this.data, 0)

    // 追加新数据
    newData.set(bytes, this.data.length)

    // 更新引用
    this.data = newData
  }

  /**
   * 判断是否为空(无未知字段)
   *
   * @returns true 如果没有未知字段
   */
  isEmpty(): boolean {
    return this.data.length === 0
  }

  /**
   * 获取原始二进制数据
   *
   * @returns 未知字段的原始数据
   *
   * 注意:返回的是内部数组的引用,不要修改!
   * 如需修改,请先调用 slice() 复制。
   */
  toBytes(): Uint8Array {
    return this.data
  }

  /**
   * 获取数据长度(字节数)
   *
   * @returns 未知字段数据的总字节数
   */
  getLength(): number {
    return this.data.length
  }

  /**
   * 清空所有未知字段
   */
  clear(): void {
    this.data = new Uint8Array(0)
  }

  /**
   * 克隆未知字段对象
   *
   * @returns 新的 UnknownFields 对象(深拷贝)
   */
  clone(): UnknownFields {
    const cloned = new UnknownFields()
    if (this.data.length > 0) {
      // 深拷贝数据
      cloned.data = new Uint8Array(this.data)
    }
    return cloned
  }

  /**
   * 合并另一个 UnknownFields 对象的数据
   *
   * @param other 要合并的 UnknownFields 对象
   */
  mergeFrom(other: UnknownFields): void {
    if (!other.isEmpty()) {
      this.append(other.toBytes())
    }
  }

  /**
   * 判断两个 UnknownFields 是否相等
   *
   * @param other 要比较的对象
   * @returns true 如果内容完全相同
   */
  equals(other: UnknownFields): boolean {
    if (this.data.length !== other.data.length) {
      return false
    }

    for (let i = 0; i < this.data.length; i++) {
      if (this.data[i] !== other.data[i]) {
        return false
      }
    }

    return true
  }

  /**
   * 调试输出
   *
   * @returns 未知字段的十六进制表示
   */
  toString(): string {
    if (this.isEmpty()) {
      return '[UnknownFields: empty]'
    }

    // 转换为十六进制字符串(最多显示前 32 字节)
    const maxBytes = Math.min(32, this.data.length)
    let hex = ''

    for (let i = 0; i < maxBytes; i++) {
      const byte = this.data[i]
      hex += (byte < 16 ? '0' : '') + byte.toString(16)
      if (i < maxBytes - 1) {
        hex += ' '
      }
    }

    if (this.data.length > maxBytes) {
      hex += ` ... (${this.data.length} bytes total)`
    }

    return `[UnknownFields: ${hex}]`
  }
}