import { APIClient } from "./ApiClient";
import { VMFileDisk, VMInfo } from "./VMApi";

export type DiskImageFormat =
  | { format: "Raw"; is_sparse: boolean }
  | { format: "QCow2"; virtual_size?: number }
  | { format: "GzCompressedQCow2" }
  | { format: "GzCompressedRaw" }
  | { format: "XzCompressedQCow2" }
  | { format: "XzCompressedRaw" };

export type DiskImage = {
  file_size: number;
  file_name: string;
  name: string;
  created: number;
} & DiskImageFormat;

export class DiskImageApi {
  /**
   * Upload a new disk image file to the server
   */
  static async Upload(
    file: File,
    progress: (progress: number) => void
  ): Promise<void> {
    const fd = new FormData();
    fd.append("file", file);

    await APIClient.exec({
      method: "POST",
      uri: "/disk_images/upload",
      formData: fd,
      upProgress: progress,
    });
  }

  /**
   * Get the list of disk images
   */
  static async GetList(): Promise<DiskImage[]> {
    return (
      await APIClient.exec({
        method: "GET",
        uri: "/disk_images/list",
      })
    ).data;
  }

  /**
   * Download disk image file
   */
  static async Download(
    file: DiskImage,
    progress: (p: number) => void
  ): Promise<Blob> {
    return (
      await APIClient.exec({
        method: "GET",
        uri: `/disk_images/${file.file_name}`,
        downProgress(e) {
          progress(Math.floor(100 * (e.progress / e.total)));
        },
      })
    ).data;
  }

  /**
   * Convert disk image file
   */
  static async Convert(
    file: DiskImage,
    dest_file_name: string,
    dest_format: DiskImageFormat
  ): Promise<void> {
    await APIClient.exec({
      method: "POST",
      uri: `/disk_images/${file.file_name}/convert`,
      jsonData: { ...dest_format, dest_file_name },
    });
  }

  /**
   * Backup VM disk into image disks library
   */
  static async BackupVMDisk(
    vm: VMInfo,
    disk: VMFileDisk,
    dest_file_name: string,
    format: DiskImageFormat
  ): Promise<void> {
    await APIClient.exec({
      uri: `/vm/${vm.uuid}/disk/${disk.name}/backup`,
      method: "POST",
      jsonData: { ...format, dest_file_name },
    });
  }

  /**
   * Rename disk image file
   */
  static async Rename(file: DiskImage, name: string): Promise<void> {
    await APIClient.exec({
      method: "POST",
      uri: `/disk_images/${file.file_name}/rename`,
      jsonData: { name },
    });
  }

  /**
   * Delete disk image file
   */
  static async Delete(file: DiskImage): Promise<void> {
    await APIClient.exec({
      method: "DELETE",
      uri: `/disk_images/${file.file_name}`,
    });
  }
}