package com.oguerreiro.resilient.service.mapper;

import java.util.Set;
import java.util.stream.Collectors;

import org.mapstruct.BeanMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;

import com.oguerreiro.resilient.domain.Unit;
import com.oguerreiro.resilient.domain.Variable;
import com.oguerreiro.resilient.domain.VariableCategory;
import com.oguerreiro.resilient.domain.VariableClassType;
import com.oguerreiro.resilient.domain.VariableScope;
import com.oguerreiro.resilient.domain.VariableUnits;
import com.oguerreiro.resilient.service.dto.UnitDTO;
import com.oguerreiro.resilient.service.dto.VariableCategoryDTO;
import com.oguerreiro.resilient.service.dto.VariableClassTypeDTO;
import com.oguerreiro.resilient.service.dto.VariableDTO;
import com.oguerreiro.resilient.service.dto.VariableScopeDTO;
import com.oguerreiro.resilient.service.dto.VariableUnitsDTO;

/**
 * Mapper for the entity {@link Variable} and its DTO {@link VariableDTO}.
 */
@Mapper(componentModel = "spring")
public interface VariableMapper extends ResilientEntityMapper<VariableDTO, Variable> {
  @Mapping(target = "baseUnit", source = "baseUnit", qualifiedByName = "unitName")
  @Mapping(target = "variableScope", source = "variableScope", qualifiedByName = "variableScopeName")
  @Mapping(target = "variableCategory", source = "variableCategory", qualifiedByName = "variableCategoryName")
  @Mapping(target = "variableClassType", source = "variableClassType", qualifiedByName = "variableClassTypeName")
  @Mapping(target = "variableUnits", source = "variableUnits", qualifiedByName = "variableUnitsNameSet")
  VariableDTO toDto(Variable s);

  @Named("unitName")
  @BeanMapping(ignoreByDefault = true)
  @Mapping(target = "id", source = "id")
  @Mapping(target = "name", source = "name")
  @Mapping(target = "unitType", source = "unitType")
  @Mapping(target = "version", source = "version")
  UnitDTO toDtoUnitName(Unit unit);

  @Named("variableScopeName")
  @BeanMapping(ignoreByDefault = true)
  @Mapping(target = "id", source = "id")
  @Mapping(target = "name", source = "name")
  @Mapping(target = "version", source = "version")
  VariableScopeDTO toDtoVariableScopeName(VariableScope variableScope);

  @Named("variableCategoryName")
  @BeanMapping(ignoreByDefault = true)
  @Mapping(target = "id", source = "id")
  @Mapping(target = "name", source = "name")
  @Mapping(target = "version", source = "version")
  VariableCategoryDTO toDtoVariableCategoryName(VariableCategory variableCategory);

  @Named("variableClassTypeName")
  @BeanMapping(ignoreByDefault = true)
  @Mapping(target = "id", source = "id")
  @Mapping(target = "name", source = "name")
  @Mapping(target = "version", source = "version")
  VariableClassTypeDTO toDtoVariableClassTypeName(VariableClassType variableClassType);

  @Mapping(target = "removeVariableUnits", ignore = true)
  Variable toEntity(VariableDTO variableDTO);

  @Named("variableUnitsPropertyName")
  @BeanMapping(ignoreByDefault = true)
  @Mapping(target = "id", source = "id")
  @Mapping(target = "unit", source = "unit")
  @Mapping(target = "unitConverter", source = "unitConverter")
  @Mapping(target = "version", source = "version")
  VariableUnitsDTO toDtoVariableUnitsPropertyName(VariableUnits variableUnits);

  @Named("variableUnitsNameSet")
  default Set<VariableUnitsDTO> toDtoVariableUnitsPropertyNameSet(Set<VariableUnits> variableUnits) {
    return variableUnits.stream().map(this::toDtoVariableUnitsPropertyName).collect(Collectors.toSet());
  }
}
