// HTTP via the host. `fetch` is async (host streams the body), `fetchLocal` reads a preloaded asset
// synchronously. Ported from worker/src/fetch.ts over the same _creatorUtils bridge.

export type FetchOptions = {
  body?: any
  method?: string
  headers?: Record<string, string>
  useOnce?: boolean
  onProgress?: (progress: { loaded: number, total?: number }) => void
}

export interface FetchResponse {
  readonly status: number
  json<T = any>(): T
  text(): string
  dispose(): void
}

class FetchResponseImpl implements FetchResponse {
  readonly status: number
  private readonly _id: number
  constructor(id: number, status: number) {
    this._id = id
    this.status = status
  }
  json<T = any>(): T {
    return _creatorUtils.fetchToJson(this._id)
  }
  text(): string {
    return _creatorUtils.fetchToText(this._id)
  }
  dispose(): void {
    _creatorUtils.disposeFetch(this._id)
  }
}

export const fetch = (url: string, options: FetchOptions = {}): Promise<FetchResponse> =>
  new Promise<FetchResponse>((resolve, reject) => {
    _creatorUtils.fetch(url, options, (systemId, statusCode) => {
      resolve(new FetchResponseImpl(systemId, statusCode))
    }, reject)
  })

export const fetchLocal = (path: string): FetchResponse =>
  new FetchResponseImpl(_creatorUtils.fetchLocal(path), 200)

/** A handle to a picked / fetched file (see openFilePicker). */
export class File {
  readonly id: number
  readonly name: string
  readonly size: number
  constructor(id: number, name: string, size: number) {
    this.id = id
    this.name = name
    this.size = size
  }
}

type FormDataValue = string | number | boolean | File | FetchResponse

export class FormData {
  private _entries: [string, FormDataValue, filename?: string][] = []

  append(name: string, value: FormDataValue, filename?: string): void {
    this._entries.push([ name, value, filename ?? (typeof value === "object" ? (value as any).name : undefined) ])
  }
  delete(name: string): void {
    const index = this._entries.findIndex((i) => i[0] === name)
    if (index >= 0) this._entries.splice(index, 1)
  }
}
