package org.fuseri.moduleexercise.question;

import org.fuseri.model.dto.exercise.AnswerInQuestionCreateDto;
import org.fuseri.model.dto.exercise.QuestionCreateDto;
import org.fuseri.model.dto.exercise.QuestionDto;
import org.fuseri.model.dto.exercise.QuestionUpdateDto;
import org.fuseri.moduleexercise.answer.Answer;
import org.fuseri.moduleexercise.answer.AnswerMapper;
import org.fuseri.moduleexercise.common.DomainMapper;
import org.fuseri.moduleexercise.exercise.Exercise;
import org.fuseri.moduleexercise.exercise.ExerciseService;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Set;

/**
 * Mapper between Questions and their corresponding DTOs
 */
@Mapper(componentModel = "spring", uses = {AnswerMapper.class, ExerciseService.class})
public abstract class QuestionMapper implements DomainMapper<Question, QuestionDto> {

    @Autowired
    private ExerciseService exerciseService;

    @Autowired
    private AnswerMapper answerMapper;

    @Named("mapIdToExercise")
    public Exercise mapIdToExercise(Long id) {
        return exerciseService.find(id);
    }

    @Named("mapDtoAnswersToAnswers")
    public Set<Answer> mapDtoAnswersToAnswers(List<AnswerInQuestionCreateDto> dtos) {
        return answerMapper.fromCreateDtoList(dtos);
    }

    /**
     * Convert entity to its corresponding DTO
     *
     * @param question to be converted
     * @return corresponding DTO created from question
     */
    @Override
    @Mapping(target = "exerciseId", source = "question.exercise.id")
    public abstract QuestionDto toDto(Question question);

    /**
     * Convert DTO of type QuestionCreateDto to Question
     *
     * @param dto DTO to be converted
     * @return corresponding Question entity created from DTO
     */
    @Mapping(target = "exercise", source = "dto.exerciseId", qualifiedByName = "mapIdToExercise")
    @Mapping(target = "answers", source = "dto.answers", qualifiedByName = "mapDtoAnswersToAnswers")
    public abstract Question fromCreateDto(QuestionCreateDto dto);

    @Mapping(target = "exercise", source = "dto.exerciseId", qualifiedByName = "mapIdToExercise")
    public abstract Question fromUpdateDto(QuestionUpdateDto dto);
}
