import { ComputedRef, Ref } from "vue";
import { Proof, MediaMetadata } from "./proof";

export class UploadPromise<Type> {
  wrappedPromise: Promise<Type>;
  aborted: boolean = false;
  onAbort: (() => void) | undefined = undefined;

  constructor(wrappedPromise: Promise<Type>) {
    this.wrappedPromise = wrappedPromise;
  }

  abort() {
    this.aborted = true;
    if (this.onAbort) {
      this.onAbort();
    }
  }

  then(resolve: any, reject: any) {
    this.wrappedPromise = this.wrappedPromise.then(resolve, reject);
    return this;
  }

  catch(handler: any) {
    this.wrappedPromise = this.wrappedPromise.catch(handler);
    return this;
  }
}

export type AttachmentSendStatus = "initial" | "sending" | "sent" | "canceled" | "failed";

export type AttachmentSendInfo = {
  status: AttachmentSendStatus;
  statusDate: number; //ms
  mediaEventId: string | undefined;
  progress: number;
  promise: UploadPromise<string> | undefined;
  randomRotation: number; // For UI effects
  randomTranslationX: number; // For UI effects
  randomTranslationY: number; // For UI effects
};

export type AttachmentThumbnail = {
  data: Uint8Array;
  mimetype: string;
  size: number;
  w: number;
  h: number;
}

export type Attachment = {
  status: "loading" | "loaded";
  file: File;
  dimensions?: { width: number; height: number };
  compressedFile?: File;
  compressedDimensions?: { width: number; height: number };
  useCompressed: boolean;
  src?: string;
  proof?: Proof;
  mediaMetadata?: MediaMetadata;
  thumbnail?: AttachmentThumbnail;
  sendInfo: AttachmentSendInfo;
};

export type AttachmentBatch = {
  sendingStatus: Ref<AttachmentSendStatus>;
  sendingRootEventId: Ref<string | undefined>;
  sendingRootMessage: Ref<string | undefined>;
  progressPercent: Ref<number>;
  attachments: Attachment[];
  attachmentsSentCount: ComputedRef<number>;
  attachmentsSending: ComputedRef<Attachment[]>;
  attachmentsSent: ComputedRef<Attachment[]>;
  addFiles: (files: File[]) => void;
  removeAttachment: (attachment: Attachment) => void;
  isTooLarge: (attachment: Attachment) => boolean;
  canSend: ComputedRef<boolean>;
  send: (message: string) => Promise<any>;
  cancel: () => void;
  cancelSendAttachment: (attachment: Attachment) => void;
};
