// See https://github.com/OHIF/Viewers/blob/94a9067fe3d291d30e25a1bda5913511388edea2/platform/core/src/utils/metadataProvider/getPixelSpacingInformation.js

export default function getPixelSpacingInformation(instance) {
  // See http://gdcm.sourceforge.net/wiki/index.php/Imager_Pixel_Spacing

  // TODO: Add Ultrasound region spacing
  // TODO: Add manual calibration

  // TODO: Use ENUMS from dcmjs
  const projectionRadiographSOPClassUIDs = [
    '1.2.840.10008.5.1.4.1.1.1', //	CR Image Storage
    '1.2.840.10008.5.1.4.1.1.1.1', //	Digital X-Ray Image Storage – for Presentation
    '1.2.840.10008.5.1.4.1.1.1.1.1', //	Digital X-Ray Image Storage – for Processing
    '1.2.840.10008.5.1.4.1.1.1.2', //	Digital Mammography X-Ray Image Storage – for Presentation
    '1.2.840.10008.5.1.4.1.1.1.2.1', //	Digital Mammography X-Ray Image Storage – for Processing
    '1.2.840.10008.5.1.4.1.1.1.3', //	Digital Intra – oral X-Ray Image Storage – for Presentation
    '1.2.840.10008.5.1.4.1.1.1.3.1', //	Digital Intra – oral X-Ray Image Storage – for Processing
    '1.2.840.10008.5.1.4.1.1.12.1', //	X-Ray Angiographic Image Storage
    '1.2.840.10008.5.1.4.1.1.12.1.1', //	Enhanced XA Image Storage
    '1.2.840.10008.5.1.4.1.1.12.2', //	X-Ray Radiofluoroscopic Image Storage
    '1.2.840.10008.5.1.4.1.1.12.2.1', //	Enhanced XRF Image Storage
    '1.2.840.10008.5.1.4.1.1.12.3' // X-Ray Angiographic Bi-plane Image Storage	Retired
  ]

  const {
    PixelSpacing,
    ImagerPixelSpacing,
    SOPClassUID,
    PixelSpacingCalibrationType,
    PixelSpacingCalibrationDescription,
    EstimatedRadiographicMagnificationFactor,
    SequenceOfUltrasoundRegions
  } = instance

  const isProjection = projectionRadiographSOPClassUIDs.includes(SOPClassUID)

  const TYPES = {
    NOT_APPLICABLE: 'NOT_APPLICABLE',
    UNKNOWN: 'UNKNOWN',
    CALIBRATED: 'CALIBRATED',
    DETECTOR: 'DETECTOR'
  }

  if (!isProjection) {
    return PixelSpacing
  }

  if (isProjection && !ImagerPixelSpacing) {
    // If only Pixel Spacing is present, and this is a projection radiograph,
    // PixelSpacing should be used, but the user should be informed that
    // what it means is unknown
    return {
      PixelSpacing,
      type: TYPES.UNKNOWN,
      isProjection
    }
  } else if (
    PixelSpacing &&
    ImagerPixelSpacing &&
    PixelSpacing === ImagerPixelSpacing
  ) {
    // If Imager Pixel Spacing and Pixel Spacing are present and they have the same values,
    // then the user should be informed that the measurements are at the detector plane
    return {
      PixelSpacing,
      type: TYPES.DETECTOR,
      isProjection
    }
  } else if (
    PixelSpacing &&
    ImagerPixelSpacing &&
    PixelSpacing !== ImagerPixelSpacing
  ) {
    // If Imager Pixel Spacing and Pixel Spacing are present and they have different values,
    // then the user should be informed that these are "calibrated"
    // (in some unknown manner if Pixel Spacing Calibration Type and/or
    // Pixel Spacing Calibration Description are absent)
    return {
      PixelSpacing,
      type: TYPES.CALIBRATED,
      isProjection,
      PixelSpacingCalibrationType,
      PixelSpacingCalibrationDescription
    }
  } else if (!PixelSpacing && ImagerPixelSpacing) {
    let CorrectedImagerPixelSpacing = ImagerPixelSpacing
    if (EstimatedRadiographicMagnificationFactor) {
      // Note that in IHE Mammo profile compliant displays, the value of Imager Pixel Spacing is required to be corrected by
      // Estimated Radiographic Magnification Factor and the user informed of that.
      // TODO: should this correction be done before all of this logic?
      CorrectedImagerPixelSpacing = ImagerPixelSpacing.map(
        (pixelSpacing) =>
          pixelSpacing / EstimatedRadiographicMagnificationFactor
      )
    } else {
      console.warn(
        'EstimatedRadiographicMagnificationFactor was not present. Unable to correct ImagerPixelSpacing.'
      )
    }

    return {
      PixelSpacing: CorrectedImagerPixelSpacing,
      isProjection
    }
  } else if (
    SequenceOfUltrasoundRegions &&
    typeof SequenceOfUltrasoundRegions === 'object'
  ) {
    const { PhysicalDeltaX, PhysicalDeltaY } = SequenceOfUltrasoundRegions
    const USPixelSpacing = [PhysicalDeltaX * 10, PhysicalDeltaY * 10]

    return {
      PixelSpacing: USPixelSpacing
    }
  } else if (
    SequenceOfUltrasoundRegions &&
    Array.isArray(SequenceOfUltrasoundRegions) &&
    SequenceOfUltrasoundRegions.length > 1
  ) {
    console.warn(
      'Sequence of Ultrasound Regions > one entry. This is not yet implemented, all measurements will be shown in pixels.'
    )
  } else if (isProjection === false && !ImagerPixelSpacing) {
    // If only Pixel Spacing is present, and this is not a projection radiograph,
    // we can stop here
    return {
      PixelSpacing,
      type: TYPES.NOT_APPLICABLE,
      isProjection
    }
  }

  console.warn(
    'Unknown combination of PixelSpacing and ImagerPixelSpacing identified. Unable to determine spacing.'
  )
}
