/**
 * MessageRegistry.ets
 *
 * 消息类型注册表(可选功能)
 *
 * ⚠️ 重要说明:
 * - 普通使用场景不需要注册,可直接使用 Person.create().toBinary()
 * - 只有以下场景需要注册:
 *   1. 使用 google.protobuf.Any 类型
 *   2. 需要根据类型名动态创建消息
 *   3. JSON 与其他格式间的转换(某些情况)
 *
 * 设计理念:
 * - 注册是完全可选的
 * - 不注册不影响基本功能
 * - 只在特殊场景下才需要
 *
 * Version: 1.0.0
 * ArkTS 2025 兼容
 */

import { Message, MessageConstructor } from './Message'

/**
 * 消息类型注册表(可选功能)
 *
 * 提供消息类型的动态查找和创建功能
 *
 * 使用场景示例:
 *
 * 场景 1: 使用 google.protobuf.Any
 * ```typescript
 * import { MessageRegistry } from './protobuf-core'
 * import { Person } from './pb/Person'
 *
 * // 注册消息类型
 * MessageRegistry.register(Person)
 *
 * // 使用 Any 类型
 * const anyMsg = new Google_Protobuf_Any()
 * anyMsg.pack(person)
 * const unpacked = anyMsg.unpack<Person>()  // 需要从 typeUrl 查找类型
 * ```
 *
 * 场景 2: 动态消息创建
 * ```typescript
 * // 注册所有消息类型
 * MessageRegistry.registerAll([Person, Address, Employee])
 *
 * // 根据类型名动态创建
 * const typeName = 'test.Person'
 * const message = MessageRegistry.create(typeName, { name: 'Alice' })
 * ```
 *
 * ❌ 不需要注册的场景:
 * ```typescript
 * // 普通使用场景
 * const person = Person.create({ name: 'Alice' })
 * const binary = person.toBinary()
 * const decoded = Person.fromBinary(binary)
 * // 这些都不需要注册!
 * ```
 */
export class MessageRegistry {
  /**
   * 消息类型映射表
   *
   * key: 消息类型名称(如 "google.protobuf.Timestamp")
   * value: 消息构造器
   */
  private static readonly types = new Map<string, MessageConstructor<Message>>()

  /**
   * 注册消息类型
   *
   * ⚠️ 可选:只在需要动态查找或 Any 类型时才调用
   *
   * @param ctor 消息构造器
   *
   * 使用示例:
   * ```typescript
   * MessageRegistry.register(Person)
   * ```
   */
  static register<T extends Message>(ctor: MessageConstructor<T>): void {
    MessageRegistry.types.set(ctor.typeName, ctor as MessageConstructor<Message>)
  }

  /**
   * 批量注册消息类型
   *
   * 用于生成的索引文件中的 registerAllMessages() 函数
   *
   * @param ctors 消息构造器数组
   *
   * 使用示例:
   * ```typescript
   * MessageRegistry.registerAll([Person, Address, Employee])
   * ```
   */
  static registerAll(ctors: MessageConstructor<Message>[]): void {
    ctors.forEach(ctor => MessageRegistry.register(ctor))
  }

  /**
   * 获取消息构造器
   *
   * @param typeName 消息类型名称
   * @returns 消息构造器,如果未注册则返回 undefined
   *
   * 使用示例:
   * ```typescript
   * const ctor = MessageRegistry.get('test.Person')
   * if (ctor !== undefined) {
   *   const msg = ctor.create({ name: 'Alice' })
   * }
   * ```
   */
  static get(typeName: string): MessageConstructor<Message> | undefined {
    return MessageRegistry.types.get(typeName)
  }

  /**
   * 检查类型是否已注册
   *
   * @param typeName 消息类型名称
   * @returns true 如果已注册
   *
   * 使用示例:
   * ```typescript
   * if (MessageRegistry.has('test.Person')) {
   *   console.log('Person type is registered')
   * }
   * ```
   */
  static has(typeName: string): boolean {
    return MessageRegistry.types.has(typeName)
  }

  /**
   * 根据类型名动态创建消息
   *
   * ⚠️ 注意:需要预先调用 register() 注册类型
   *
   * @param typeName 消息类型名称
   * @param init 初始化数据(可选)
   * @returns 创建的消息对象,如果类型未注册则返回 null
   *
   * 使用示例:
   * ```typescript
   * MessageRegistry.register(Person)
   * const person = MessageRegistry.create('test.Person', { name: 'Alice' })
   * if (person !== null) {
   *   console.log(person.toJson())
   * }
   * ```
   */
  static create(typeName: string, init?: Object): Message | null {
    const ctor = MessageRegistry.get(typeName)
    if (ctor === undefined) {
      console.warn(`Message type "${typeName}" not registered. Call MessageRegistry.register() first.`)
      return null
    }
    return ctor.create(init as Partial<Message>)
  }

  /**
   * 从二进制创建消息
   *
   * ⚠️ 注意:需要预先调用 register() 注册类型
   *
   * @param typeName 消息类型名称
   * @param data 二进制数据
   * @returns 创建的消息对象,如果类型未注册则返回 null
   *
   * 使用示例:
   * ```typescript
   * MessageRegistry.register(Person)
   * const binary = new Uint8Array([...])
   * const person = MessageRegistry.fromBinary('test.Person', binary)
   * ```
   */
  static fromBinary(typeName: string, data: Uint8Array): Message | null {
    const ctor = MessageRegistry.get(typeName)
    if (ctor === undefined) {
      console.warn(`Message type "${typeName}" not registered.`)
      return null
    }
    return ctor.fromBinary(data)
  }

  /**
   * 从 JSON 创建消息
   *
   * ⚠️ 注意:需要预先调用 register() 注册类型
   *
   * @param typeName 消息类型名称
   * @param json JSON 对象
   * @returns 创建的消息对象,如果类型未注册则返回 null
   *
   * 使用示例:
   * ```typescript
   * MessageRegistry.register(Person)
   * const json = { name: 'Alice', age: 30 }
   * const person = MessageRegistry.fromJson('test.Person', json)
   * ```
   */
  static fromJson(typeName: string, json: Record<string, Object>): Message | null {
    const ctor = MessageRegistry.get(typeName)
    if (ctor === undefined) {
      console.warn(`Message type "${typeName}" not registered.`)
      return null
    }
    return ctor.fromJson(json)
  }

  /**
   * 获取所有已注册的类型名称
   *
   * @returns 类型名称数组
   *
   * 使用示例:
   * ```typescript
   * const types = MessageRegistry.getRegisteredTypes()
   * console.log('Registered types:', types)
   * ```
   */
  static getRegisteredTypes(): string[] {
    return Array.from(MessageRegistry.types.keys())
  }

  /**
   * 清空注册表
   *
   * ⚠️ 警告:此操作会清空所有已注册的类型
   *
   * 使用示例:
   * ```typescript
   * MessageRegistry.clear()
   * ```
   */
  static clear(): void {
    MessageRegistry.types.clear()
  }

  /**
   * 获取注册表大小
   *
   * @returns 已注册类型的数量
   *
   * 使用示例:
   * ```typescript
   * const count = MessageRegistry.size()
   * console.log(`${count} types registered`)
   * ```
   */
  static size(): number {
    return MessageRegistry.types.size
  }
}