/** Given the `FileReader.readAsDataURL()` based `dataURI` extracts that data into an actual Blob along with the name
 * of that Blob if provided in the URL. If no name is provided, then the name falls back to `unknown`.
 *
 * @param dataURI - The `DataUrl` potentially containing name and raw data to be converted to a Blob
 * @returns - an object containing a Blob and its name, extracted from the URI
 */
export default function dataURItoBlob(dataURILike: string) {
  // check if is dataURI
  if (dataURILike.indexOf('data:') === -1) {
    throw new Error('File is invalid: URI must be a dataURI');
  }
  const dataURI = dataURILike.slice(5);
  // split the dataURI into media and base64, with the base64 signature
  const splitted = dataURI.split(';base64,');
  // if the base64 signature is not present, the latter part will become empty
  if (splitted.length !== 2) {
    throw new Error('File is invalid: dataURI must be base64');
  }
  // extract the mime type, media parameters including the name, and the base64 string
  const [media, base64] = splitted;
  const [mime, ...mediaparams] = media.split(';');
  const type = mime || '';

  // extract the name from the parameters
  const name = decodeURI(
    // parse the parameters into key-value pairs, find a key, and extract a value
    // if no key is found, then the name is unknown
    mediaparams.map((param) => param.split('=')).find(([key]) => key === 'name')?.[1] || 'unknown'
  );

  // Built the Uint8Array Blob parameter from the base64 string.
  try {
    const binary = atob(base64);
    const array = new Array(binary.length);
    for (let i = 0; i < binary.length; i++) {
      array[i] = binary.charCodeAt(i);
    }
    // Create the blob object
    const blob = new window.Blob([new Uint8Array(array)], { type });

    return { blob, name };
  } catch (error) {
    throw new Error('File is invalid: ' + (error as Error).message);
  }
}
