import util from "../plugins/utils";

export default {
  data() {
    return {
      sendStatuses: Object.freeze({
        INITIAL: 0,
        SENDING: 1,
        SENT: 2,
        CANCELED: 3,
        FAILED: 4,
      }),
      sendingStatus: 0,
      sendingPromise: null,
      sendingRootEventId: null,
      sendingAttachments: [],
    }
  },
  computed: {
    attachmentsSentCount() {
      return this.sendingAttachments ? this.sendingAttachments.reduce((a, elem, ignoredidx, ignoredarray) => elem.status == this.sendStatuses.SENT ? a + 1 : a, 0) : 0
    },
    attachmentsSending() {
      return this.sendingAttachments ? this.sendingAttachments.filter(elem => elem.status == this.sendStatuses.INITIAL || elem.status == this.sendStatuses.SENDING) : []
    },
    attachmentsSent() {
      this.sortSendingAttachments();
      return this.sendingAttachments ? this.sendingAttachments.filter(elem => elem.status == this.sendStatuses.SENT) : []
    },
  },
  methods: {
    sendAttachments(text, attachments) {
      this.sendingStatus = this.sendStatuses.SENDING;

      this.sendingAttachments = attachments.map((attachment) => {
        let file = (() => {
          // other than file type image
          if(attachment instanceof File) {
            return attachment;
          } else {
            if (attachment.scaled && attachment.useScaled) {
              // Send scaled version of image instead!
              return attachment.scaled;
            } else {
              // Send actual file image when not scaled!
              return attachment.actualFile;
            }
          }
        })();
        let sendInfo = {
          id: attachment.name,
          status: this.sendStatuses.INITIAL,
          statusDate: Date.now,
          mediaEventId: undefined,
          attachment: file,
          preview: attachment.image,
          progress: 0,
          randomRotation: 0,
          randomTranslationX: 0,
          randomTranslationY: 0
        }; 
        attachment.sendInfo = sendInfo;
        return sendInfo;
      });

      this.sendingPromise = util.sendTextMessage(this.$matrix.matrixClient, this.room.roomId, text)
        .then((eventId) => {
          this.sendingRootEventId = eventId;

          // Use the eventId as a thread root for all the media
          let promiseChain = Promise.resolve();
          const getItemPromise = (index) => {
            if (index < this.sendingAttachments.length) {
              const item = this.sendingAttachments[index];
              if (item.status !== this.sendStatuses.INITIAL) {
                return getItemPromise(++index);
              }
              item.status = this.sendStatuses.SENDING;
              const itemPromise = util.sendFile(this.$matrix.matrixClient, this.room.roomId, item.attachment, ({ loaded, total }) => {
                if (loaded == total) {
                  item.progress = 100;
                } else if (total > 0) {
                  item.progress = 100 * loaded / total;
                }
              }, eventId)
                .then((mediaEventId) => {
                  // Look at last item rotation, flipping the sign on this, so looks more like a true stack
                  let signR = 1;
                  let signX = 1;
                  let signY = 1;
                  if (this.attachmentsSent.length > 0) {
                    if (this.attachmentsSent[0].randomRotation >= 0) {
                      signR = -1;
                    }
                    if (this.attachmentsSent[0].randomTranslationX >= 0) {
                      signX = -1;
                    }
                    if (this.attachmentsSent[0].randomTranslationY >= 0) {
                      signY = -1;
                    }
                  }
                  item.randomRotation = signR * (2 + Math.random() * 10);
                  item.randomTranslationX = signX * Math.random() * 20;
                  item.randomTranslationY = signY * Math.random() * 20;
                  item.mediaEventId = mediaEventId;
                  item.status = this.sendStatuses.SENT;
                  item.statusDate = Date.now;
                }).catch(ignorederr => {
                  if (item.promise.aborted) {
                    item.status = this.sendStatuses.CANCELED;
                  } else {
                    console.error("ERROR", ignorederr);
                    item.status = this.sendStatuses.FAILED;
                  }
                });
              item.promise = itemPromise;
              return itemPromise.then(() => getItemPromise(++index));
            }
            else return Promise.resolve();
          };

          return promiseChain.then(() => getItemPromise(0));
        })
        .then(() => {
          this.sendingStatus = this.sendStatuses.SENT;
          this.sendingAttachments = [];
          this.sendingRootEventId = null;
        })
        .catch((err) => {
          console.error("ERROR", err);
        });
      return this.sendingPromise;
    },

    cancelSendAttachments() {
      this.sendingAttachments.toReversed().forEach(item => {
        this.cancelSendAttachmentItem(item);
      });
      this.sendingStatus = this.sendStatuses.CANCELED;
      if (this.sendingRootEventId && this.room) {

        // Redact all media we already sent, plus the root event
        let promises = this.sendingAttachments.filter((item) => item.mediaEventId !== undefined).map((item) => this.$matrix.matrixClient.redactEvent(this.room.roomId, item.mediaEventId, undefined, { reason: "cancel" }));
        promises.push(this.$matrix.matrixClient.redactEvent(this.room.roomId, this.sendingRootEventId, undefined, { reason: "cancel" }));
        Promise.allSettled(promises)
          .then(() => {
            console.log("Message redacted");
          })
          .catch((err) => {
            console.log("Redaction failed: ", err);
          });
      }
    },

    cancelSendAttachmentItem(item) {
      if (item.promise && item.status != this.sendStatuses.INITIAL) {
        item.promise.abort();
      }
      item.status = this.sendStatuses.CANCELED;
    },

    sortSendingAttachments() {
      this.sendingAttachments.sort((a, b) => b.statusDate - a.statusDate);
    },
  }
}