
package de.ivu.elect.presentation.exchange;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.Nullable;
import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import javax.inject.Inject;

import org.apache.deltaspike.core.api.scope.ConversationGroup;
import org.apache.deltaspike.core.api.scope.GroupedConversationScoped;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.exchange.control.FileFormat;
import de.ivu.elect.business.security.control.ElectCommonPrincipal;
import de.ivu.elect.business.wahl.boundary.WahlSelectChangeEvent;
import de.ivu.elect.business.wahl.boundary.WahlterminSelectChangeEvent;
import de.ivu.elect.presentation.View;

@GroupedConversationScoped
@ConversationGroup(SupportedFileFormatErmittler.class)
public class SupportedFileFormatErmittler implements Serializable {

  private static final long serialVersionUID = 1L;

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

  @Inject
  private transient ImportExportSelectState importExportSelectState;

  @Inject
  private transient SupportedFileFormatErmittlerViewResolver supportedFileFormatErmittlerViewResolver;

  @Inject
  private transient ElectCommonPrincipal principal;

  @Nullable
  private Map<String, List<FileFormat>> viewIdToFileFormatsMap = null;

  public boolean isSupportedFileFormatVorhanden(String viewId) {
    return !getSupportedFileFormats(viewId).isEmpty();
  }

  public List<FileFormat> getSupportedFileFormats(String viewId) {
    if (viewId == null) {
      LOG.error("ViewId darf nicht null sein.");
      return Collections.emptyList();
    }

    if (viewIdToFileFormatsMap == null) {
      viewIdToFileFormatsMap = createViewIdToFileFormatsMap();
    }

    List<FileFormat> supportedFileFormats = viewIdToFileFormatsMap.get(viewId);

    if (supportedFileFormats == null) {
      LOG.error("ViewId gehört keinem AbstractImportExportView an: " + viewId);
      return Collections.emptyList();
    }

    return supportedFileFormats;
  }

  @SuppressWarnings({"rawtypes", "unchecked"})
  private Map<String, List<FileFormat>> createViewIdToFileFormatsMap() {
    importExportSelectState.save();

    Map<String, List<FileFormat>> map = new ConcurrentHashMap<>();

    for (AbstractImportExportView importExportView : supportedFileFormatErmittlerViewResolver.getViews()) {
      View viewAnnotation = importExportView.getClass().getAnnotation(View.class);
      try {
        // ELECT-12336
        if (principal.hasUseCasePermission(viewAnnotation.useCase())) {
          map.put(viewAnnotation.viewId(), importExportView.getSupportedFileFormatsUnsorted());
        } else {
          map.put(viewAnnotation.viewId(), Collections.emptyList());
        }
      } catch (Exception ex) {
        // Fange alle Exceptions, da das Pattern ziemlich unberechnebar ist.
        // ExchangeContext nicht gültig -> keine Dateiformate verfügbar
        map.put(viewAnnotation.viewId(), Collections.emptyList());

        // elect Log-Level auf INFO lassen, Fehler werden schnell verdeckt...
        LOG.info("Unterstütztes Dateiformate des Exchange-Views kann nicht ermittelt werden [" + viewAnnotation.viewId() + "] [" + importExportView.getClass()
            .getName() + "] ", ex);
      }
    }

    importExportSelectState.restore();

    return map;
  }

  public void reset() {
    viewIdToFileFormatsMap = null;
  }

  /*
   * ExchangeContexte sind von der zur Bearbeitung ausgewählten Wahl abhängig.
   */
  public void onWahlSelectChangeEvent(@Observes(notifyObserver = Reception.IF_EXISTS) WahlSelectChangeEvent event) {
    reset();
  }

  /*
   * ExchangeContexte sind vom zur Bearbeitung ausgewählten Wahltermin abhängig.
   */
  public void onWahlterminSelectChangeEvent(@Observes(notifyObserver = Reception.IF_EXISTS) WahlterminSelectChangeEvent event) {
    reset();
  }


}
