import * as  Log  from "#util/log.ts"


const log = Log.create({ service: "state" })

interface Entry {
  state: any
  dispose?: (state: any) => Promise<void>
}

// 两层Map结构：
// 第一层：key (项目目录) → 第二层Map
// 第二层：init函数 → Entry对象
//以路径 和 状态构造函数为key的map，存储的是Entry,Entry.state 是具体的state，Entity.dispose则是销毁状态的引用
//使用这个map是为了保证一个文件夹只有一个state容器，
const recordsByKey = new Map<string, Map<any, Entry>>()


/**
 * 
 * @param root  
 * @param init 
 * @param dispose 
 * @returns 返回一个 ()=>S
 * 
 */
export function GetOrCreate<S>(
  root: () => string,
  init: () => S,
  dispose?: (state: Awaited<S>) => Promise<void>) {
  return () => {
    const key = root()
    let entries = recordsByKey.get(key)
    if (!entries) {
      entries = new Map<string, Entry>()
      recordsByKey.set(key, entries)
    }
    const exists = entries.get(init)
    if (exists)
      return exists.state as S
    const state = init()
    entries.set(init, {
      state,
      dispose,
    })
    return state
  }
}

export async function dispose(key: string) {
  const entries = recordsByKey.get(key)
  if (!entries) return

  log.info("waiting for state disposal to complete", { key })

  let disposalFinished = false

  setTimeout(() => {
    if (!disposalFinished) {
      log.warn(
        "state disposal is taking an unusually long time - if it does not complete in a reasonable time, please report this as a bug",
        { key },
      )
    }
  }, 10000).unref()

  const tasks: Promise<void>[] = []
  for (const entry of entries.values()) {
    if (!entry.dispose) continue

    const task = Promise.resolve(entry.state)
      .then((state) => entry.dispose!(state))
      .catch((error) => {
        log.error("Error while disposing state:", { error, key })
      })

    tasks.push(task)
  }
  entries.clear()
  recordsByKey.delete(key)
  await Promise.all(tasks)
  disposalFinished = true
  log.info("state disposal completed", { key })
}

