package com.oguerreiro.resilient.service.mapper;

import java.util.List;
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.DashboardComponent;
import com.oguerreiro.resilient.domain.DashboardComponentDetail;
import com.oguerreiro.resilient.domain.DashboardComponentOrganization;
import com.oguerreiro.resilient.domain.Organization;
import com.oguerreiro.resilient.domain.Variable;
import com.oguerreiro.resilient.service.dto.DashboardComponentDTO;
import com.oguerreiro.resilient.service.dto.DashboardComponentDetailDTO;
import com.oguerreiro.resilient.service.dto.DashboardComponentOrganizationDTO;
import com.oguerreiro.resilient.service.dto.OrganizationDTO;
import com.oguerreiro.resilient.service.dto.VariableDTO;

/**
 * Mapper for the entity {@link DashboardComponent} and its DTO {@link DashboardComponentDTO}.
 */
@Mapper(componentModel = "spring")
public interface DashboardComponentMapper extends ResilientEntityMapper<DashboardComponentDTO, DashboardComponent> {
  @Mapping(target = "dashboardComponentDetails", source = "dashboardComponentDetails", qualifiedByName = "dashboardComponentDetailNameList")
  @Mapping(target = "dashboardComponentOrganizations", source = "dashboardComponentOrganizations", qualifiedByName = "dashboardComponentOrganizationNameList")
  DashboardComponentDTO toDto(DashboardComponent dashboardComponent);

  @Mapping(target = "removeDashboardComponentDetail", ignore = true)
  DashboardComponent toEntity(DashboardComponentDTO dashboardComponentDTO);

  @Named("variableName")
  @BeanMapping(ignoreByDefault = true)
  @Mapping(target = "id", source = "id")
  @Mapping(target = "code", source = "code")  // Needed to show in the select list immediately, otherwise it waits for full page rendering
  @Mapping(target = "name", source = "name")
  @Mapping(target = "version", source = "version")
  VariableDTO toDtoVariableName(Variable variable);

  @Named("targetDashboardComponentName")
  @BeanMapping(ignoreByDefault = true)
  @Mapping(target = "id", source = "id")
  @Mapping(target = "name", source = "name")
  @Mapping(target = "version", source = "version")
  DashboardComponentDTO toDtoTargetDashboardComponentName(DashboardComponent targetDashboardComponent);

  @Named("dashboardComponentDetailPropertyName")
  @BeanMapping(ignoreByDefault = true)
  @Mapping(target = "id", source = "id")
  @Mapping(target = "name", source = "name")
  @Mapping(target = "color", source = "color")
  @Mapping(target = "help", source = "help")
  @Mapping(target = "indexOrder", source = "indexOrder")
  @Mapping(target = "variable", source = "variable", qualifiedByName = "variableName")
  @Mapping(target = "targetDashboardComponent", source = "targetDashboardComponent", qualifiedByName = "targetDashboardComponentName")
  @Mapping(target = "version", source = "version")
  DashboardComponentDetailDTO toDtoDashboardComponentDetailPropertyName(
      DashboardComponentDetail dashboardComponentDetail);

  @Named("dashboardComponentDetailNameList")
  default List<DashboardComponentDetailDTO> toDtoDashboardComponentDetailPropertyNameSet(
      List<DashboardComponentDetail> dashboardComponentDetail) {
    return dashboardComponentDetail.stream().map(this::toDtoDashboardComponentDetailPropertyName).collect(
        Collectors.toList());
  }

  @Named("organizationName")
  @BeanMapping(ignoreByDefault = true)
  @Mapping(target = "id", source = "id")
  @Mapping(target = "code", source = "code")
  @Mapping(target = "version", source = "version")
  OrganizationDTO toDtoOrganizationName(Organization organization);

  @Named("dashboardComponentOrganizationPropertyName")
  @BeanMapping(ignoreByDefault = true)
  @Mapping(target = "id", source = "id")
  @Mapping(target = "organization", source = "organization", qualifiedByName = "organizationName")
  @Mapping(target = "version", source = "version")
  DashboardComponentOrganizationDTO toDtoDashboardComponentOrganizationPropertyName(
      DashboardComponentOrganization dashboardComponentOrganization);

  @Named("dashboardComponentOrganizationNameList")
  default List<DashboardComponentOrganizationDTO> toDtoDashboardComponentOrganizationPropertyNameSet(
      List<DashboardComponentOrganization> dashboardComponentOrganization) {
    return dashboardComponentOrganization.stream().map(this::toDtoDashboardComponentOrganizationPropertyName).collect(
        Collectors.toList());
  }
}
