import { ensureFile } from "$std/fs/ensure_file.ts";

/**
 * @param src url of file
 * @param dest destination file. If `useFileName` is true, this should be the destination directory
 * @param [useFileName] whether to use the inferred file name from `src`
 */

export async function downloadFile(
  src: string,
  dest: string,
  useFileName?: boolean,
) {
  if (!(src.startsWith("http://") || src.startsWith("https://"))) {
    throw new TypeError("URL must start with be http:// or https://");
  }

  const fileName = src.split("/").at(-1);

  const res = await fetch(src);
  if (!res.ok) {
    throw new Deno.errors.BadResource(
      `Request failed with status ${res.status}`,
    );
  } else if (!res.body) {
    throw new Deno.errors.UnexpectedEof(
      `The download url ${src} doesn't contain a file to download`,
    );
  } else if (res.status === 404) {
    throw new Deno.errors.NotFound(
      `The requested url "${src}" could not be found`,
    );
  }

  const blob = await res.blob();
  const buffer = await blob.arrayBuffer();
  const uint8array = new Uint8Array(buffer);

  await ensureFile(useFileName ? dest + fileName : dest);
  await Deno.writeFile(dest, uint8array);
}
