func getQuestionStep()

in iOS/MyStudies/MyStudies/Views/Steps/ActivityStep/ActivityQuestionStep.swift [273:943]


  func getQuestionStep() -> ORKQuestionStep? {

    if Utilities.isValidValue(someObject: resultType as AnyObject?) {

      var questionStepAnswerFormat: ORKAnswerFormat?  // Contains the answerFormat for specific question Type

      var questionStep: ORKQuestionStep?  // Contains the QuestionStep instance
      var placeholderText: String? = ""

      // Assigning the answerFormat for the questionStep based on questionStep
      switch QuestionStepType(rawValue: (resultType as? String)!)! as QuestionStepType {
      case .scale:

        if Utilities.isValidValue(
          someObject: formatDict?[kStepQuestionScaleMaxValue] as AnyObject?
        )
          && Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionScaleMinValue] as AnyObject?
          )
          && Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionScaleDefaultValue] as AnyObject?
          )
          && Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionScaleStep] as AnyObject?
          )
          && Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionScaleVertical] as AnyObject?
          )
        {
          let maxDesc = formatDict?[kStepQuestionScaleMaxDesc] as? String
          let minDesc = formatDict?[kStepQuestionScaleMinDesc] as? String

          // Checking if difference is divisible
          let difference =
            (formatDict?[kStepQuestionScaleMaxValue] as? Int)! - (formatDict?[kStepQuestionScaleMinValue] as? Int)!
          let divisibleValue = difference % (formatDict?[kStepQuestionScaleStep] as? Int)!
          let stepsValue = difference / (formatDict?[kStepQuestionScaleStep] as? Int)!
          let defaultPosition = (formatDict?[kStepQuestionScaleDefaultValue] as? Int)!
          var defaultValue = defaultPosition * stepsValue

          // Setting the default Value if Exist
          if defaultValue > (formatDict?[kStepQuestionScaleMaxValue] as? Int)! {
            defaultValue = (formatDict?[kStepQuestionScaleMaxValue] as? Int)!
          }

          if ((formatDict?[kStepQuestionScaleMaxValue] as? Int)! != (formatDict?[kStepQuestionScaleMinValue] as? Int)!)
            && divisibleValue == 0 && (stepsValue >= 1 && stepsValue <= 13)
          {

            questionStepAnswerFormat = ORKAnswerFormat.scale(
              withMaximumValue: (formatDict?[kStepQuestionScaleMaxValue] as? Int)!,
              minimumValue: (formatDict?[kStepQuestionScaleMinValue] as? Int)!,
              defaultValue: (formatDict?[kStepQuestionScaleDefaultValue] as? Int)!,
              step: (formatDict?[kStepQuestionScaleStep] as? Int)!,
              vertical: (formatDict?[kStepQuestionScaleVertical] as? Bool)!,
              maximumValueDescription: maxDesc,
              minimumValueDescription: minDesc
            )
            // Setting the Max & Min Images if exist
            if Utilities.isValidValue(
              someObject: (formatDict?[kStepQuestionScaleMaxImage] as? String as AnyObject)
            )
              && Utilities.isValidValue(
                someObject: (formatDict?[kStepQuestionScaleMinImage] as? String as AnyObject)
              )
            {
              let minImageBase64String = (formatDict![kStepQuestionScaleMinImage] as? String)!
              let minNormalImage = imageFromBase64(minImageBase64String)
              
              let maxImageBase64String = (formatDict![kStepQuestionScaleMaxImage] as? String)!
              let maxNormalImage = imageFromBase64(maxImageBase64String)
              
              (questionStepAnswerFormat as? ORKScaleAnswerFormat)!.minimumImage = minNormalImage
              (questionStepAnswerFormat as? ORKScaleAnswerFormat)!.maximumImage = maxNormalImage
            }
          } else {
            return nil
          }
        } else {
          return nil
        }
      case .continuousScale:

        if Utilities.isValidValue(
          someObject: formatDict?[kStepQuestionContinuosScaleMaxFractionDigits]
            as AnyObject?
        )
          && formatDict?[kStepQuestionContinuosScaleVertical] != nil
        {

          let maxDesc = formatDict?[kStepQuestionContinuosScaleMaxDesc] as? String
          let minDesc = formatDict?[kStepQuestionContinuosScaleMinDesc] as? String
          var maxValue = 0.0
          var minValue = -1.0
          var defaultValue = 0.0
          if Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionContinuosScaleMaxValue] as AnyObject?
          ) {
            maxValue = (formatDict?[kStepQuestionContinuosScaleMaxValue] as? Double)!

          } else {
            if let value = (formatDict?[kStepQuestionContinuosScaleMaxValue] as? Double) {

              if value > 0 {
                minValue = (formatDict?[kStepQuestionContinuosScaleMaxValue] as? Double)!
              }
            }
          }
          if Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionContinuosScaleMaxValue] as AnyObject?
          ) {
            minValue = (formatDict?[kStepQuestionContinuosScaleMinValue] as? Double)!

          } else {
            if let value = (formatDict?[kStepQuestionContinuosScaleMinValue] as? Double) {

              if value > 0 {
                minValue = (formatDict?[kStepQuestionContinuosScaleMinValue] as? Double)!
              }
            }
          }

          if Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionContinuosScaleDefaultValue]
              as AnyObject?
          ) {
            defaultValue = (formatDict?[kStepQuestionContinuosScaleDefaultValue] as? Double)!

          } else {
            if let value = (formatDict?[kStepQuestionContinuosScaleDefaultValue] as? Double) {

              if value > 0 {
                defaultValue = (formatDict?[kStepQuestionContinuosScaleDefaultValue] as? Double)!
              }
            }
          }

          if (formatDict?[kStepQuestionContinuosScaleMinValue] as? Double)!
            != (formatDict?[kStepQuestionContinuosScaleMaxValue] as? Double)!
          {

            questionStepAnswerFormat = ORKAnswerFormat.continuousScale(
              withMaximumValue: maxValue,
              minimumValue: minValue,
              defaultValue: defaultValue,
              maximumFractionDigits: (formatDict?[kStepQuestionContinuosScaleMaxFractionDigits] as? Int)!,
              vertical: (formatDict?[kStepQuestionContinuosScaleVertical] as? Bool)!,
              maximumValueDescription: maxDesc,
              minimumValueDescription: minDesc
            )

            // setting the min & max images if exists
            if Utilities.isValidValue(
              someObject: (formatDict?[kStepQuestionContinuosScaleMaxImage] as? String as AnyObject)
            )
              && Utilities.isValidValue(
                someObject: (formatDict?[kStepQuestionContinuosScaleMinImage] as? String as AnyObject)
              )
            {

              let minImageBase64String = (formatDict![kStepQuestionContinuosScaleMinImage] as? String)!
              let minNormalImage = imageFromBase64(minImageBase64String)

              let maxImageBase64String = (formatDict![kStepQuestionContinuosScaleMaxImage] as? String)!
              let maxNormalImage = imageFromBase64(maxImageBase64String)

              (questionStepAnswerFormat as? ORKContinuousScaleAnswerFormat)!
                .minimumImage = minNormalImage
              (questionStepAnswerFormat as? ORKContinuousScaleAnswerFormat)!
                .maximumImage = maxNormalImage
            }
          } else {
            return nil
          }
        } else {
          return nil
        }
      case .textscale:

        if Utilities.isValidObject(
          someObject: formatDict?[kStepQuestionTextScaleTextChoices] as AnyObject?
        )
          && Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionTextScaleDefault] as AnyObject?
          )
          && Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionTextScaleVertical] as AnyObject?
          )
        {

          let textChoiceArray: [ORKTextChoice]?

          let defaultValue = (formatDict?[kStepQuestionTextScaleDefault] as? Int)!
          self.textScaleDefaultValue = "\(defaultValue)"

          let textChoiceDict =
            formatDict?[kStepQuestionTextScaleTextChoices] as? [Any]
            ?? []
          textChoiceArray = self.getTextChoices(dataArray: textChoiceDict).0

          questionStepAnswerFormat = ORKAnswerFormat.textScale(
            with: textChoiceArray!,
            defaultIndex: defaultValue - 1,
            vertical: (formatDict?[kStepQuestionTextScaleVertical] as? Bool)!
          )
        } else {
          return nil
        }
      case .valuePicker:

        if Utilities.isValidObject(
          someObject: formatDict?[kStepQuestionTextScaleTextChoices] as AnyObject?
        ) {

          let textChoiceArray: [ORKTextChoice]?

          let textChoiceDict =
            formatDict?[kStepQuestionTextScaleTextChoices] as? [Any]
            ?? []
          textChoiceArray = self.getTextChoices(dataArray: textChoiceDict).0

          questionStepAnswerFormat = ORKAnswerFormat.valuePickerAnswerFormat(
            with: textChoiceArray!
          )
        } else {
          return nil
        }
      case .imageChoice:

        if Utilities.isValidObject(
          someObject: formatDict?[kStepQuestionImageChoices] as AnyObject?
        ) {

          let imageChoiceArray: [ORKImageChoice]?
          imageChoiceArray = self.getImageChoices(
            dataArray: (formatDict?[kStepQuestionImageChoices] as? NSArray)!
          )
          if imageChoiceArray == nil {
            return nil
          }
          questionStepAnswerFormat = ORKAnswerFormat.choiceAnswerFormat(
            with: imageChoiceArray!
          )

        } else {
          return nil
        }
      case .textChoice:
        if Utilities.isValidObject(
          someObject: formatDict?[kStepQuestionTextChoiceTextChoices] as AnyObject?
        )
          && Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionTextChoiceSelectionStyle] as AnyObject?
          )
        {

          let textChoiceDict =
            formatDict?[kStepQuestionTextChoiceTextChoices] as? [Any]
            ?? []

          
          
          let choiceResult = ((formatDict?[kStepQuestionTextChoiceSelectionStyle] as? String)!)
          == kStepQuestionTextChoiceSelectionStyleSingle ?
          self.getTextChoicesSingleSelection(dataArray: textChoiceDict) : self.getTextChoices(dataArray: textChoiceDict)
          
          
          
//          let choiceResult = self.getTextChoicesSingleSelection(dataArray: textChoiceDict)
          var otherChoice: OtherChoice? = choiceResult.1

          otherChoice = (otherChoice == nil) ? OtherChoice() : otherChoice

          let textChoiceArray: [ORKTextChoice]? = choiceResult.0

          if ((formatDict?[kStepQuestionTextChoiceSelectionStyle] as? String)!)
            == kStepQuestionTextChoiceSelectionStyleSingle
          {
            // single choice
            questionStepAnswerFormat = ORKTextChoiceAnswerFormat(
              style: ORKChoiceAnswerStyle.singleChoice,
              textChoices: textChoiceArray!
            )
          } else if ((formatDict?[kStepQuestionTextChoiceSelectionStyle] as? String)!)
            == kStepQuestionTextChoiceSelectionStyleMultiple
          {
            // multiple choice
            questionStepAnswerFormat = ORKTextChoiceAnswerFormat(
              style: ORKChoiceAnswerStyle.multipleChoice,
              textChoices: textChoiceArray!
            )
          } else {
            return nil
          }

          questionStep = QuestionStep(
            identifier: key!,
            title: "",
            question: title!,
            answer: questionStepAnswerFormat!,
            otherChoice: otherChoice!
          )
          // By default a step is skippable
          if skippable == false {
            questionStep?.isOptional = false
          } else {
            questionStep?.isOptional = true
          }
          // setting the placeholder Value if exist any
          if Utilities.isValidValue(someObject: placeholderText as AnyObject?) {
            questionStep?.placeholder = placeholderText
          }
          questionStep?.text = text
          return questionStep

        } else {
          return nil
        }

      case .boolean:
        questionStepAnswerFormat = ORKBooleanAnswerFormat()

      case .numeric:

        if Utilities.isValidValue(
          someObject: formatDict?[kStepQuestionNumericStyle] as AnyObject?
        ) {

          var maxValue = formatDict?[kStepQuestionNumericMaxValue] as? NSNumber

          let minValue = formatDict?[kStepQuestionNumericMinValue] as? NSNumber

          if maxValue != nil && maxValue == 0 {
            if let minValue = minValue,
              !(Int(truncating: minValue) < 0)
            {
              maxValue = nil  // Max value can't be zero if the min value is greater than 0.
            }
          }

          if Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionNumericPlaceholder] as AnyObject?
          ) {
            placeholderText = formatDict?[kStepQuestionNumericPlaceholder] as? String
          }

          let localizedQuestionStepAnswerFormatUnit = NSLocalizedString(
            (formatDict?[kStepQuestionNumericUnit] as? String)!,
            comment: ""
          )

          let style =
            ((formatDict?[kStepQuestionNumericStyle] as? String)! == "Decimal")
            ? 0 : 1

          switch ORKNumericAnswerStyle(rawValue: style)! as ORKNumericAnswerStyle {
          case .integer:  // Integer Question Step

            if Utilities.isValidValue(someObject: self.healthDataKey as AnyObject?) {

              let quantityTypeId: HKQuantityTypeIdentifier =
                HKQuantityTypeIdentifier
                .init(
                  rawValue: self.healthDataKey!
                )

              let quantityType = HKQuantityType.quantityType(
                forIdentifier: quantityTypeId
              )

              var unit: HKUnit?
              // Setting the Unit if valid unit exist
              if localizedQuestionStepAnswerFormatUnit != ""
                && self.isUnitValid(
                  unit: localizedQuestionStepAnswerFormatUnit
                )
              {
                unit = HKUnit.init(from: localizedQuestionStepAnswerFormatUnit)
              }

              questionStepAnswerFormat = ORKHealthKitQuantityTypeAnswerFormat.init(
                quantityType: quantityType!,
                unit: unit,
                style: ORKNumericAnswerStyle.integer
              )

            } else {
              if minValue != nil || maxValue != nil {
                questionStepAnswerFormat = ORKNumericAnswerFormat.init(
                  style: ORKNumericAnswerStyle.integer,
                  unit: localizedQuestionStepAnswerFormatUnit,
                  minimum: minValue,
                  maximum: maxValue
                )
              } else {
                questionStepAnswerFormat = ORKAnswerFormat.integerAnswerFormat(
                  withUnit: localizedQuestionStepAnswerFormatUnit
                )
              }
            }
          case .decimal:  // Decimal Question Step
            if Utilities.isValidValue(someObject: self.healthDataKey as AnyObject?) {

              let quantityTypeId = HKQuantityTypeIdentifier.init(
                rawValue: self.healthDataKey!
              )
              var unit: HKUnit?
              // Setting the Unit if valid unit exist
              if localizedQuestionStepAnswerFormatUnit != ""
                && self.isUnitValid(
                  unit: localizedQuestionStepAnswerFormatUnit
                )
              {
                unit = HKUnit.init(from: localizedQuestionStepAnswerFormatUnit)
              }
              questionStepAnswerFormat = ORKHealthKitQuantityTypeAnswerFormat.init(
                quantityType: HKQuantityType.quantityType(
                  forIdentifier: quantityTypeId
                )!,
                unit: unit,
                style: ORKNumericAnswerStyle.decimal
              )

            } else {

              if minValue != nil || maxValue != nil {
                questionStepAnswerFormat = ORKNumericAnswerFormat.init(
                  style: ORKNumericAnswerStyle.decimal,
                  unit: localizedQuestionStepAnswerFormatUnit,
                  minimum: minValue,
                  maximum: maxValue
                )
              } else {
                questionStepAnswerFormat = ORKAnswerFormat.decimalAnswerFormat(
                  withUnit: localizedQuestionStepAnswerFormatUnit
                )
              }
            }
          @unknown default:
            break
          }
        } else {
          return nil
        }
      case .timeOfDay:
        questionStepAnswerFormat = ORKAnswerFormat.timeOfDayAnswerFormat()

      case .date:

        if Utilities.isValidValue(
          someObject: formatDict?[kStepQuestionDateStyle] as AnyObject?
        ) {

          let dateFormatter = DateFormatter()
          dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"

          var dateRange: DateRange? = DateRange.defaultValue

          if Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionDateRange] as AnyObject?
          ) {

            dateRange = DateRange.init(
              rawValue: (formatDict?[kStepQuestionDateRange] as? String)!
            )
          }

          let defaultDate: NSDate? =
            dateFormatter.date(
              from: (formatDict?[kStepQuestionDateDefault] as? String)!
            ) as NSDate?
          var minimumDate: NSDate? =
            dateFormatter.date(
              from: (formatDict?[kStepQuestionDateMinDate] as? String)!
            ) as NSDate?
          var maximumDate: NSDate? =
            dateFormatter.date(
              from: (formatDict?[kStepQuestionDateMaxDate] as? String)!
            ) as NSDate?

          // Setting the date Range
          switch dateRange! {
          case .untilCurrent:  // Any date less than Current Date
            maximumDate = Date.init(timeIntervalSinceNow: 0) as NSDate
          case .afterCurrent:  // Any date greater than Current
            minimumDate = Date.init(timeIntervalSinceNow: 86400) as NSDate
          case .defaultValue: break
          case .custom: break
          }

          switch DateStyle(rawValue: (formatDict?[kStepQuestionDateStyle] as? String)!)!
            as DateStyle
          {

          case .date:
            questionStepAnswerFormat = ORKAnswerFormat.dateAnswerFormat(
              withDefaultDate: defaultDate as Date?,
              minimumDate: minimumDate as Date?,
              maximumDate: maximumDate as Date?,
              calendar: NSCalendar.current
            )

          case .dateAndTime:
            questionStepAnswerFormat = ORKAnswerFormat.dateTime(
              withDefaultDate: defaultDate as Date?,
              minimumDate: minimumDate as Date?,
              maximumDate: maximumDate as Date?,
              calendar: NSCalendar.current
            )

          }

        } else {
          return nil
        }
      case .text:

        if Utilities.isValidValue(
          someObject: formatDict?[kStepQuestionTextMultipleLines] as AnyObject?
        ) {

          if Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionNumericPlaceholder] as AnyObject?
          ) {
            placeholderText = formatDict?[kStepQuestionNumericPlaceholder] as? String
          }

          var answerFormat = ORKAnswerFormat.textAnswerFormat()

          if Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionTextValidationRegex] as AnyObject?
          )
            && Utilities
              .isValidValue(
                someObject: formatDict?[kStepQuestionTextInvalidMessage] as AnyObject?
              )
          {

            var regex: NSRegularExpression?

            regex = try? NSRegularExpression(
              pattern: (formatDict?[kStepQuestionTextValidationRegex] as? String)!,
              options: []
            )

            if regex != nil {
              answerFormat = ORKAnswerFormat.textAnswerFormat(
                withValidationRegularExpression: regex!,
                invalidMessage: (formatDict?[kStepQuestionTextInvalidMessage] as? String)!
              )
            }
          } else {
            answerFormat.invalidMessage = nil
          }

          if Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionTextMaxLength] as AnyObject?
          ) {
            answerFormat.maximumLength = (formatDict?[kStepQuestionTextMaxLength] as? Int)!
          } else {
            answerFormat.maximumLength = 0
          }

          answerFormat.multipleLines = (formatDict?[kStepQuestionTextMultipleLines] as? Bool)!
          questionStepAnswerFormat = answerFormat

        } else {
          return nil
        }
      case .email:

        questionStepAnswerFormat = ORKAnswerFormat.emailAnswerFormat()
        if Utilities.isValidValue(
          someObject: formatDict?[kStepQuestionNumericPlaceholder] as AnyObject?
        ) {
          placeholderText = formatDict?[kStepQuestionNumericPlaceholder] as? String
        }
      case .timeInterval:

        if Utilities.isValidValue(
          someObject: formatDict?[kStepQuestionTimeIntervalStep] as AnyObject?
        ) {
          let defaultTimeInterval: Double?

          if Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionTimeIntervalDefault] as AnyObject?
          ) {
            defaultTimeInterval = Double(
              (formatDict?[kStepQuestionTimeIntervalDefault] as? Int)!
            )

          } else {
            defaultTimeInterval = Double(0.0)
          }

          if (formatDict?[kStepQuestionTimeIntervalStep] as? Int)! >= 1
            && (formatDict?[kStepQuestionTimeIntervalStep] as? Int)! <= 30
          {

            questionStepAnswerFormat = ORKAnswerFormat.timeIntervalAnswerFormat(
              withDefaultInterval: defaultTimeInterval!,
              step: (formatDict?[kStepQuestionTimeIntervalStep] as? Int)!
            )
          } else {
            return nil
          }
        } else {
          return nil
        }
      case .height:

        if Utilities.isValidValue(
          someObject: formatDict?[kStepQuestionHeightMeasurementSystem] as AnyObject?
        ) {

          let measurementSystem: ORKMeasurementSystem?
          switch HeightMeasurementSystem(
            rawValue: (formatDict?[kStepQuestionHeightMeasurementSystem] as? String)!
          )! {
          case .local:
            measurementSystem = .local
          case .metric:
            measurementSystem = .metric
          case .us:
            measurementSystem = .USC
          }
          questionStepAnswerFormat = ORKAnswerFormat.heightAnswerFormat(
            with: measurementSystem!
          )

          if Utilities.isValidValue(
            someObject: formatDict?[kStepQuestionNumericPlaceholder] as AnyObject?
          ) {
            placeholderText = formatDict?[kStepQuestionNumericPlaceholder] as? String
          }
        } else {
          return nil
        }
      case .location:
        if Utilities.isValidValue(
          someObject: formatDict?[kStepQuestionLocationUseCurrentLocation] as AnyObject?
        ) {
          let answerFormat = ORKAnswerFormat.locationAnswerFormat()
          answerFormat.useCurrentLocation = (formatDict?[kStepQuestionLocationUseCurrentLocation] as? Bool)!

          questionStepAnswerFormat = answerFormat
        } else {
          return nil
        }
      default: break
      }

      questionStep = ORKQuestionStep(
        identifier: key!,
        title: title!,
        answer: questionStepAnswerFormat
      )  // TBD: need to verify with API
      // By default a step is skippable
      if skippable == false {
        questionStep?.isOptional = false
      }
      // setting the placeholder Value if exist any
      if Utilities.isValidValue(someObject: placeholderText as AnyObject?) {
        questionStep?.placeholder = placeholderText
      }
      questionStep?.text = text
      return questionStep!
    } else {
      return nil
    }
  }