export type Flow = 'leftToRight' | 'rightToLeft'

export class Queue<T> {
  private queue: T[] = []

  /**
   * @param itemLength 队列长度
   * @param flow 队列方向
   */
  constructor(
    private itemLength = 20,
    private flow: Flow = 'rightToLeft'
  ) {}

  push(item: T, noLimit?: boolean): void {
    this.queue.push(item)
    this._handle(noLimit)
  }

  unshift(item: T, noLimit?: boolean): void {
    this.queue.unshift(item)
    this._handle(noLimit)
  }

  pop(): T | undefined {
    return this.queue.pop()
  }

  shift(): T | undefined {
    return this.queue.shift()
  }

  resetLimitState(): void {
    this._handle()
  }

  clear(): void {
    this.queue.length = 0
  }

  get(): T[] {
    return this.queue
  }

  set(value: T[], noLimit?: boolean): void {
    this.queue = value
    this._handle(noLimit)
  }

  get length(): number {
    return this.queue.length
  }

  private _handle(noLimit = false) {
    if (this.queue.length > this.itemLength && !noLimit) {
      if (this.flow === 'leftToRight') {
        this.queue.splice(this.itemLength, this.queue.length - this.itemLength)
      } else {
        this.queue.splice(0, this.queue.length - this.itemLength)
      }
    }
  }
}

export class QueueMap<T> {
  map = new Map<string, Queue<T>>()

  constructor(
    private itemLength = 20,
    private flow: Flow = 'rightToLeft'
  ) {}

  get(key: string): T[] | undefined {
    return this.map.get(key)?.get()
  }

  set(key: string, value: T[], noLimit: boolean): void {
    const queue = new Queue<T>(this.itemLength, this.flow)

    queue.set(value, true)
    this.map.set(key, queue)
  }

  delete(key: string): boolean {
    this.map.get(key)?.clear()
    return this.map.delete(key)
  }

  resetLimitState(): void {
    this.map.forEach((item) => item.resetLimitState())
  }

  clear(): void {
    this.map.forEach((item) => item.clear())
    this.map.clear()
  }

  values(): T[] {
    return [...this.map.values()].map((item) => item.get()).flat()
  }

  /**
   * 克隆当前 QueueMap 实例
   * 用于确保状态更新时创建新的对象引用
   */
  clone(): QueueMap<T> {
    const newQueueMap = new QueueMap<T>(this.itemLength, this.flow)

    // 复制所有现有的队列
    for (const [key, queue] of this.map.entries()) {
      newQueueMap.set(key, queue.get(), false)
    }

    return newQueueMap
  }
}
