
package de.ivu.elect.exchange.rolle;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import javax.inject.Inject;

import de.ivu.elect.business.benutzerverwaltung.entity.RolleArt;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.benutzerverwaltung.boundary.RolleDAO;
import de.ivu.elect.business.benutzerverwaltung.entity.Rolle;
import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.exchange.control.FileFormat;
import de.ivu.elect.business.security.UseCasePermission;

public abstract class AbstractDefaultRolleMapper<T extends ExchangeRolleDTO> implements RolleMapper {

  public static final String FORMAT_NAME = "file.format.rolle.default";

  private static final Logger LOG = LoggerFactory.getLogger(AbstractDefaultRolleMapper.class);

  @Inject
  private transient RolleDAO dao;

  public AbstractDefaultRolleMapper() {
    super();
  }

  protected abstract T createEntity();

  protected T mappeEntity(Rolle from) {
    T to = createEntity();
    to.setName(from.getName());
    to.setRolleArt(from.getRolleArt().name());
    to.setBeschreibung(from.getBeschreibung());
    setRollen(from, to);
    return to;
  }

  protected Rolle mappeEntity(T from) {
    Rolle to = new Rolle();
    to.setName(from.getName());
    to.setRolleArt(mappeRolleArt(from));
    to.setBeschreibung(from.getBeschreibung());
    setRollen(from, to);
    return to;
  }

  private RolleArt mappeRolleArt(T from) {
    if (StringUtils.isBlank(from.getRolleArt())) {
      return RolleArt.FACHLICH;
    }
    return RolleArt.valueOf(from.getRolleArt());
  }

  private void setRollen(Rolle from, T to) {
    to.setPermissions(getPermissionWithAttachedRolle(from).stream().map(this::mappePermission).collect(Collectors.toList()));
  }

  private Collection<UseCasePermission> getPermissionWithAttachedRolle(Rolle from) {
    return dao.findByPrimaryKey(from.getPk()).getRecht().stream().sorted(Comparator.comparing(Enum::name)).collect(Collectors.toList());
  }

  private void setRollen(T from, Rolle to) {
    if (from.getPermissions() == null) {
      return;
    }

    List<UseCasePermission> toPermissions = new ArrayList<>();
    for (DefaultExchangePermission permission : from.getPermissions()) {
      try {
        toPermissions.add(mappePermission(permission));
      } catch (IllegalArgumentException ise) {
        // WASDE-261 unbekannte Permission weglassen
        LOG.warn(ise.getMessage());
      }
    }

    to.addPermissions(toPermissions);
  }

  private DefaultExchangePermission mappePermission(UseCasePermission from) {
    return new DefaultExchangePermission(from.name());
  }

  private UseCasePermission mappePermission(DefaultExchangePermission from) {
    return UseCasePermission.valueOf(from.getName());
  }

  @Override
  public FileFormat getFileFormat() {
    return new FileFormat(FORMAT_NAME, getFileType());
  }

  protected abstract FileType getFileType();
}
