
package de.ivu.elect.business.system.boundary;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import javax.enterprise.inject.Instance;
import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.business.system.control.SystemStatusOptionResolver;
import de.ivu.elect.business.system.entity.SystemStatusOptionGroup;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.jee.presentation.status.OutputSeverity;
import de.ivu.elect.jee.presentation.status.StatusEntry;
import de.ivu.elect.jee.presentation.status.StatusOption;
import de.ivu.elect.jee.presentation.status.StatusOptionGroup;


import static java.util.stream.Collectors.toList;

public class SystemUebersicht {

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

  @Inject
  private transient Messages messages;

  @Inject
  private transient Instance<SystemStatusOptionResolver> resolvers;

  public SystemUebersicht() {
    super();
  }

  public StatusEntry ermittleStatus(StatusOption statusOption) {
    for (SystemStatusOptionResolver resolver : resolvers) {
      if (resolver.isSuitable(statusOption)) {
        try {
          return resolver.resolveStatus(statusOption);
        } catch (Exception ex) {
          LOG.warn("StatusOption: " + statusOption + ", resolver: " + resolver + ", " + ex.getMessage(), ex);

          return new StatusEntry(getMessage("system.uebersicht.resolver.error", statusOption, ex.getLocalizedMessage()), OutputSeverity.ERROR);
        }
      }
    }

    return new StatusEntry(getMessage("system.uebersicht.resolver.not.found", statusOption), OutputSeverity.ERROR);
  }

  public List<StatusOptionGroup> getStatusOptionGroups(Mandant mandant) {
    Map<SystemStatusOptionGroup, List<StatusOption>> map = new EnumMap<>(SystemStatusOptionGroup.class);

    resolvers.forEach(
        resolver -> map.computeIfAbsent(resolver.getSystemStatusOptionGroup(), x -> new ArrayList<>()).addAll(resolver.getStatusOptions(mandant)));

    return map.entrySet().stream() //
        .sorted(Entry.comparingByKey()) //
        .map(this::asStatusOptionGroup) //
        .collect(Collectors.toList());
  }

  private StatusOptionGroup asStatusOptionGroup(Entry<SystemStatusOptionGroup, List<StatusOption>> entry) {
    return new StatusOptionGroup( //
        getMessage(entry.getKey()), //
        entry.getValue().stream().sorted(Comparator.comparing(one -> one.getType().toString())).collect(toList()) //
    );
  }

  private String getMessage(String msgKey, Object... params) {
    return messages.getMessageForMessageKey(msgKey, params);
  }

  private String getMessage(Enum<?> enumValue) {
    return messages.lokalisiere(enumValue);
  }
}
