text: import cornerstone from 'cornerstone-core';
  import cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader';
  import { api } from 'dicomweb-client';
  import DICOMWeb from '../DICOMWeb';
  
  const getImageId = imageObj => {
    if (!imageObj) {
      return;
    }
  
    return typeof imageObj.getImageId === 'function'
      ? imageObj.getImageId()
      : imageObj.url;
  };
  
  const findImageIdOnStudies = (studies, displaySetInstanceUid) => {
    const study = studies.find(study => {
      const displaySet = study.displaySets.some(
        displaySet => displaySet.displaySetInstanceUid === displaySetInstanceUid
      );
      return displaySet;
    });
    const { seriesList = [] } = study;
    const { instances = [] } = seriesList[0] || {};
    const instance = instances[0];
  
    return getImageId(instance);
  };
  
  const someInvalidStrings = strings => {
    const stringsArray = Array.isArray(strings) ? strings : [strings];
    const emptyString = string => !string;
    let invalid = stringsArray.some(emptyString);
    return invalid;
  };
  
  const getImageInstance = dataset => {
    return dataset && dataset.images && dataset.images[0];
  };
  
  const getImageInstanceId = imageInstance => {
    return getImageId(imageInstance);
  };
  
  const fetchIt = (url, headers = DICOMWeb.getAuthorizationHeader()) => {
    return fetch(url, headers).then(response => response.arrayBuffer());
  };
  
  const cornerstoneRetriever = imageId => {
    return cornerstone.loadAndCacheImage(imageId).then(image => {
      return image && image.data && image.data.byteArray.buffer;
    });
  };
  
  const wadorsRetriever = (
    url,
    studyInstanceUID,
    seriesInstanceUID,
    sopInstanceUID,
    headers = DICOMWeb.getAuthorizationHeader()
  ) => {
    const config = {
      url,
      headers,
    };
    const dicomWeb = new api.DICOMwebClient(config);
  
    return dicomWeb.retrieveInstance({
      studyInstanceUID,
      seriesInstanceUID,
      sopInstanceUID,
    });
  };
  
  const getImageLoaderType = imageId => {
    const loaderRegExp = /^\w+\:/;
    const loaderType = loaderRegExp.exec(imageId);
  
    return (
      (loaderRegExp.lastIndex === 0 &&
        loaderType &&
        loaderType[0] &&
        loaderType[0].replace(':', '')) ||
      ''
    );
  };
  
  const DicomLoaderService = new (class {
    getLocalData(dataset, studies) {
      if (dataset && dataset.localFile) {
        // Use referenced imageInstance
        const imageInstance = getImageInstance(dataset);
        let imageId = getImageInstanceId(imageInstance);
  
        // or Try to get it from studies
        if (someInvalidStrings(imageId)) {
          imageId = findImageIdOnStudies(studies, dataset.displaySetInstanceUid);
        }
  
        if (!someInvalidStrings(imageId)) {
          return cornerstoneWADOImageLoader.wadouri.loadFileRequest(imageId);
        }
      }
    }
  
    getDataByImageType(dataset) {
      const imageInstance = getImageInstance(dataset);
  
      if (imageInstance) {
        const imageId = getImageInstanceId(imageInstance);
        let getDicomDataMethod = fetchIt;
        const loaderType = getImageLoaderType(imageId);
  
        switch (loaderType) {
          case 'dicomfile':
            getDicomDataMethod = cornerstoneRetriever.bind(this, imageId);
            break;
          case 'wadors':
            const url = imageInstance.getData().wadoRoot;
            const studyInstanceUID = imageInstance.getStudyInstanceUID();
            const seriesInstanceUID = imageInstance.getSeriesInstanceUID();
            const sopInstanceUID = imageInstance.getSOPInstanceUID();
            const invalidParams = someInvalidStrings([
              url,
              studyInstanceUID,
              seriesInstanceUID,
              sopInstanceUID,
            ]);
            if (invalidParams) {
              return;
            }
  
            getDicomDataMethod = wadorsRetriever.bind(
              this,
              url,
              studyInstanceUID,
              seriesInstanceUID,
              sopInstanceUID
            );
            break;
          case 'wadouri':
            // Strip out the image loader specifier
            imageId = imageId.substring(imageId.indexOf(':') + 1);
  
            if (someInvalidStrings(imageId)) {
              return;
            }
            getDicomDataMethod = fetchIt.bind(this, imageId);
            break;
        }
  
        return getDicomDataMethod();
      }
    }
  
    getDataByDatasetType(dataset) {
      const {
        studyInstanceUid,
        seriesInstanceUid,
        sopInstanceUid,
        authorizationHeaders,
        wadoRoot,
        wadoUri,
      } = dataset;
      // Retrieve wadors or just try to fetch wadouri
      if (!someInvalidStrings(wadoRoot)) {
        return wadorsRetriever(
          wadoRoot,
          studyInstanceUid,
          seriesInstanceUid,
          sopInstanceUid,
          authorizationHeaders
        );
      } else if (!someInvalidStrings(wadoUri)) {
        return fetchIt(wadoUri, { headers: authorizationHeaders });
      }
    }
  
    *getLoaderIterator(dataset, studies) {
      yield this.getLocalData(dataset, studies);
      yield this.getDataByImageType(dataset);
      yield this.getDataByDatasetType(dataset);
    }
  
    findDicomDataPromise(dataset, studies) {
      const loaderIterator = this.getLoaderIterator(dataset, studies);
      // it returns first valid retriever method.
      for (const loader of loaderIterator) {
        if (loader) {
          return loader;
        }
      }
  
      // in case of no valid loader
      throw new Error('Invalid dicom data loader');
    }
  })();
  
  export default DicomLoaderService;
  