import { Observable } from "rxjs";

export interface AttachmentPreviewImage {
  type: "image";
  /**
   * An array of sources for the image (inspired by `<source>` used in `<picture>`).
   */
  sources?: Array<{
    /**
     * e.g. "image/png" or "image/webp"
     */
    type: string;
    /**
     * URL to fetch the image.
     */
    url: string;
    /**
     * Pixel width of the image (not natural width).
     */
    width: number;
  }>;
  /**
   * The default source URL for the image. Useful for referencing the original
   * file when there are no previews available.
   */
  url: string;
}

export interface AttachmentPreviewAudio {
  type: "audio";
  url: string;
  audioType: string;
}

export interface AttachmentPreviewUnavailable {
  type: "unavailable";
}

export interface AttachmentPreviewPending {
  type: "pending";
}

export type AttachmentPreview =
  | AttachmentPreviewAudio
  | AttachmentPreviewImage
  | AttachmentPreviewUnavailable
  | AttachmentPreviewPending;

// --

export interface AttachmentDownloadUrlAvailable {
  type: "available";
  url: string;
}

export interface AttachmentDownloadUrlPending {
  type: "pending";
}

export interface AttachmentDownloadUrlRefreshing {
  type: "refreshing";
}

export interface AttachmentDownloadUrlUnavailable {
  type: "unavailable";
}

export type AttachmentDownloadUrl =
  | AttachmentDownloadUrlAvailable
  | AttachmentDownloadUrlPending
  | AttachmentDownloadUrlRefreshing
  | AttachmentDownloadUrlUnavailable;

// --

/**
 * The attachment has completed uploading.
 */
export interface AttachmentUploadComplete {
  type: "complete";
}

/**
 * The attachment has failed to upload.
 */
export interface AttachmentUploadFailed {
  type: "failed";
}

/**
 * The attachment is queued for upload.
 */
export interface AttachmentUploadQueued {
  type: "queued";
}

/**
 * No upload information is available for the attachment. This usually indicates
 * that the attachment isn't being uploaded locally (it might be being uploaded
 * by another user, or was uploaded successfully in the past).
 */
export interface AttachmentUploadUnknown {
  type: "unknown";
}

/**
 * The attachment is actively being uploaded.
 */
export interface AttachmentUploadUploading {
  type: "uploading";
  bytesUploaded: number;
  bytesTotal: number;
}

export type AttachmentUpload =
  | AttachmentUploadComplete
  | AttachmentUploadFailed
  | AttachmentUploadQueued
  | AttachmentUploadUnknown
  | AttachmentUploadUploading;

// --

export interface AttachmentService {
  getDownloadUrl(attachmentId: string): Observable<AttachmentDownloadUrl>;
  getPreview(attachmentId: string): Observable<AttachmentPreview>;
  getUploadState(id: string): Observable<AttachmentUpload>;
  seedPreview(attachmentId: string, file: File): void;
  /**
   * Start uploading a file, resolving to an `id` after the start of the upload
   * has been confirmed by the backend. After being resolved, the collab central
   * authority can verify the existance of the attachment.
   */
  upload(file: File): Promise<{ id: string }>;
}
