package cz.muni.fi.pa165.core.common;

import cz.muni.fi.pa165.model.dto.common.DomainObjectDto;
import cz.muni.fi.pa165.model.dto.common.Result;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.springframework.data.domain.Page;

import java.util.List;

/**
 * The DomainMapper interface provides methods to convert between DTOs and entities, as well as lists of them.
 * It also defines methods to map the create and update DTOs to entities, and a method to convert a Page of entities to a Result DTO.
 *
 * @param <E> the type of the entity class
 * @param <T> the type of the DTO class
 * @param <C> the type of the create DTO class
 * @param <U> the type of the update DTO class
 */
public interface DomainMapper<E extends DomainObject, T extends DomainObjectDto, C extends DomainObjectDto, U extends DomainObjectDto> {

	/**
	 * Converts an entity object to a DTO object.
	 *
	 * @param entity the entity object to convert
	 * @return the corresponding dto object
	 */

	T toDto(E entity);

	/**
	 * Converts a DTO object to an entity object.
	 *
	 * @param dto the DTO object to convert
	 * @return the corresponding entity object
	 */
	E fromDto(T dto);

	/**
	 * Converts a list of entity objects to a list of DTO objects.
	 *
	 * @param entities the list of entity objects to convert
	 * @return the corresponding list of DTO objects
	 */
	List<T> toDtoList(List<E> entities);

	/**
	 * Converts a create DTO object to an entity object.
	 *
	 * @param dto the create DTO object to convert
	 * @return the corresponding entity object
	 */
	E fromCreateDto(C dto);

	/**
	 * Converts an update DTO object to an entity object.
	 *
	 * @param dto the update DTO object to convert
	 * @return the corresponding entity object
	 */
	E fromUpdateDto(U dto);

	/**
	 * Converts a Page of entities to a Result DTO.
	 *
	 * @param source the Page of entities to convert
	 * @return the corresponding Result DTO
	 */
	@Mappings({
			@Mapping(target = "total", expression = "java(source.getTotalElements())"),
			@Mapping(target = "page", expression = "java(source.getNumber())"),
			@Mapping(target = "pageSize", expression = "java(source.getSize())"),
			@Mapping(target = "items", expression = "java(toDtoList(source.getContent()))")
	})
	Result<T> toResult(Page<E> source);
}
