import { del, get } from 'idb-keyval';
import { deckSelector, docSelector, SlideTemplate } from '@deckdeckgo/editor';
import { uploadFileIC } from '../providers/storage/storage.ic';
const imagesRegex = /((<deckgo-lazy-img.*?)(img-src=)(.*?")(.*?[^"]*)(.*?"))/g;
export const uploadDeckBackgroundAssets = async ({ deck, identity, syncWindow, storageBucket }) => {
  const { background } = deck.data;
  if (!background) {
    return {
      src: undefined,
      storageFile: undefined
    };
  }
  const results = [...background.matchAll(imagesRegex)];
  // Only one image in the background is currently supported
  if ((results === null || results === void 0 ? void 0 : results.length) !== 1) {
    return {
      src: undefined,
      storageFile: undefined
    };
  }
  const imgSrc = results[0][5];
  return uploadData({
    src: imgSrc,
    key: `/decks/${deck.id}`,
    identity,
    syncWindow,
    msg: 'deckdeckgo_sync_deck_background',
    folder: 'images',
    storageBucket
  });
};
export const uploadSlideAssets = async ({ deckId, slide, identity, syncWindow, storageBucket }) => {
  const images = await uploadSlideImages({
    deckId,
    slide,
    identity,
    syncWindow,
    storageBucket
  });
  const chart = await uploadSlideChart({ deckId, slide, identity, syncWindow, storageBucket });
  return {
    images,
    chart
  };
};
const uploadSlideImages = async ({ deckId, slide, identity, syncWindow, storageBucket }) => {
  const { content } = slide.data;
  if (!content) {
    return undefined;
  }
  const results = [...content.matchAll(imagesRegex)];
  const promises = results === null || results === void 0 ? void 0 : results.map((result) => {
    const imgSrc = result[5];
    return uploadData({
      src: imgSrc,
      key: `/decks/${deckId}/slides/${slide.id}`,
      selector: `${deckSelector} > *[slide_id="${slide.id}"]`,
      identity,
      syncWindow,
      msg: 'deckdeckgo_sync_slide_image',
      folder: 'images',
      storageBucket
    });
  });
  return Promise.all(promises);
};
const uploadSlideChart = async ({ deckId, slide, identity, syncWindow, storageBucket }) => {
  const { content, template, attributes } = slide.data;
  if (!content || template !== SlideTemplate.CHART || !attributes) {
    return undefined;
  }
  const { src } = attributes;
  return uploadData({
    src,
    key: `/decks/${deckId}/slides/${slide.id}`,
    selector: `${deckSelector} > *[slide_id="${slide.id}"]`,
    identity,
    syncWindow,
    msg: 'deckdeckgo_sync_slide_chart',
    folder: 'data',
    storageBucket
  });
};
const uploadData = ({ src, key, selector, identity, syncWindow, msg, folder, storageBucket }) => {
  return new Promise(async (resolve, reject) => {
    try {
      if (!src || src === '' || /^https?:\/\/.+\/.+$/.test(src)) {
        resolve({
          src: undefined,
          storageFile: undefined
        });
        return;
      }
      const data = await get(src);
      if (!data) {
        // We didn't the corresponding image. Instead of crashing an error we go through, user will notice that nothing is displayed.
        // Better than blocking the all process and reaching an intermediate state.
        resolve({
          src: undefined,
          storageFile: undefined
        });
        return;
      }
      // 1. We upload the file to the storage cloud
      const storageFile = await uploadFileIC({
        data,
        folder,
        maxSize: 10485760,
        identity,
        storageBucket
      });
      if (!storageFile) {
        reject(`Data ${src} upload has failed.`);
        return;
      }
      // 2. We update the DOM and IDB (currently saved data)
      await syncWindow({
        msg,
        data: {
          src,
          key,
          selector,
          storageFile
        }
      });
      // 3. All good, we don't need the image in the indexedDB anymore
      await del(src);
      resolve({
        src,
        storageFile
      });
    }
    catch (err) {
      reject(err);
    }
  });
};
export const uploadParagraphImages = async ({ docId, paragraph, identity, syncWindow, storageBucket }) => {
  const { children, nodeName, attributes } = paragraph.data;
  // The paragraph itself might be an image
  if (nodeName === 'deckgo-lazy-img') {
    const syncStorage = await uploadParagraphImage({
      imgSrc: attributes === null || attributes === void 0 ? void 0 : attributes['img-src'],
      docId,
      paragraphId: paragraph.id,
      identity,
      syncWindow,
      storageBucket
    });
    return [syncStorage];
  }
  if (!children || children.length <= 0) {
    return undefined;
  }
  const content = children.join('');
  const results = [...content.matchAll(imagesRegex)];
  const promises = results === null || results === void 0 ? void 0 : results.map((result) => {
    const imgSrc = result[5];
    return uploadParagraphImage({
      imgSrc: imgSrc,
      docId,
      paragraphId: paragraph.id,
      identity,
      syncWindow,
      storageBucket
    });
  });
  return Promise.all(promises);
};
const uploadParagraphImage = async ({ imgSrc, docId, paragraphId, identity, syncWindow, storageBucket }) => {
  return uploadData({
    src: imgSrc,
    key: `/docs/${docId}/paragraphs/${paragraphId}`,
    selector: `${docSelector} > article *[paragraph_id="${paragraphId}"]`,
    identity,
    syncWindow,
    msg: 'deckdeckgo_sync_paragraph_image',
    folder: 'images',
    storageBucket
  });
};
