class R4ProgramStageToFhirQuestionnaireResponseTransformer extends AbstractProgramStageToFhirQuestionnaireResponseTransformer {

    @Override
    protected boolean transformInternal( @Nonnull FhirClient fhirClient, @Nonnull DhisToFhirTransformerContext context, @Nonnull RuleInfo<ProgramStageRule> ruleInfo, @Nonnull Map<String, Object> scriptVariables,
        @Nonnull ScriptedEvent input, @Nonnull IBaseResource output, @Nonnull IBaseResource trackedEntityResource )
    {
        final Event event = (Event) input.getDhisResource();
        final ProgramStage programStage = input.getProgramStage();
        final QuestionnaireResponse fhirQuestionnaireResponse = (QuestionnaireResponse) output;

        final IBaseReference questionnaireReference = createAssignedFhirReference( context, ruleInfo, scriptVariables,
            DhisResourceType.PROGRAM_STAGE_METADATA, event.getProgramStageId(), FhirResourceType.QUESTIONNAIRE );
        fhirQuestionnaireResponse.setQuestionnaireElement( questionnaireReference == null ? null :
            new CanonicalType( questionnaireReference.getReferenceElement().getValue() ) );
        fhirQuestionnaireResponse.setItem( null );

        fhirQuestionnaireResponse.setBasedOn( createAssignedFhirReferences( context, ruleInfo, scriptVariables,
            DhisResourceType.ENROLLMENT, event.getEnrollmentId(), FhirResourceType.CARE_PLAN ) );
        EventStatusExtensionUtils.setValue( fhirQuestionnaireResponse, event.getStatus(), ResourceFactory::createType );
        fhirQuestionnaireResponse.setAuthored( Date.from( event.getEventDate().toInstant() ) );
        DueDateExtensionUtils.setValue( fhirQuestionnaireResponse, event.getDueDate() == null ? null :
            Date.from( event.getDueDate().toInstant() ), ResourceFactory::createType );

        LocationExtensionUtils.setValue( fhirQuestionnaireResponse, createAssignedFhirReference( context, ruleInfo, scriptVariables,
            DhisResourceType.ORGANIZATION_UNIT, event.getOrgUnitId(), FhirResourceType.LOCATION ) );
        fhirQuestionnaireResponse.setSubject( new Reference( trackedEntityResource.getIdElement() ) );

        if ( event.getStatus() == EventStatus.COMPLETED )
        {
            fhirQuestionnaireResponse.setStatus( QuestionnaireResponseStatus.COMPLETED );
        }
        else
        {
            fhirQuestionnaireResponse.setStatus( QuestionnaireResponseStatus.INPROGRESS );
        }

        final AbstractValueTypeDhisToFhirTransformerUtils valueTypeUtils =
            TransformerUtils.getScriptVariable( scriptVariables, ScriptVariable.VALUE_TYPE_UTILS, AbstractValueTypeDhisToFhirTransformerUtils.class );

        for ( final DataValue dataValue : event.getDataValues() )
        {
            programStage.getOptionalDataElement( createIdReference( dataValue.getDataElementId() ) ).filter( dataElement -> valueTypeUtils.isSupportedValueType( dataElement.getElement().getValueType() ) ).ifPresent( dataElement -> {
                final QuestionnaireResponseItemComponent item = fhirQuestionnaireResponse.addItem();
                item.setLinkId( dataValue.getDataElementId() );
                item.addAnswer().setValue( (Type) valueTypeUtils.convert(
                    dataValue.getValue(), dataElement.getElement().getValueType(), dataElement.getElement().getOptionSet() ) );
            } );
        }

        return true;
    }

    public  R4ProgramStageToFhirQuestionnaireResponseTransformer( @Nonnull ScriptExecutor scriptExecutor, @Nonnull LockManager lockManager, @Nonnull SystemRepository systemRepository, @Nonnull FhirResourceRepository fhirResourceRepository,
        @Nonnull FhirResourceMappingRepository resourceMappingRepository, @Nonnull FhirDhisAssignmentRepository fhirDhisAssignmentRepository, @Nonnull TrackedEntityMetadataService trackedEntityMetadataService,
        @Nonnull TrackedEntityRuleRepository trackedEntityRuleRepository, @Nonnull ProgramMetadataService programMetadataService );

}