package de.ivu.elect.business.system.control.files;

import java.io.Serializable;
import java.util.Collections;
import java.util.List;

import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.persistence.EntityNotFoundException;

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

import de.ivu.elect.business.system.boundary.SystemLogWriter;
import de.ivu.elect.business.system.control.files.cleaner.FileCleaner;
import de.ivu.elect.business.system.control.files.cleaner.FileCleanerBucket;
import de.ivu.elect.business.system.control.files.cleaner.FileCleanerFinder;
import de.ivu.elect.business.system.entity.SystemLogQuelle;

// @Stateless ELECTKOM-2576 keine Transaktion
public class FileCleanup implements Serializable {

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

  private static final long serialVersionUID = 1L;

  @Inject
  private transient FileCleanupTransaction fileCleanupTransaction;

  @Inject
  private transient FileCleanerFinder fileCleanerFinder;

  @Inject
  private transient SystemLogWriter systemLogWriter;

  public boolean isEtwasZuBereinigen() {
    return fileCleanupTransaction.isDateibereinugungAktiviert() && fileCleanupTransaction.isServerVerzeichnisVerfuegbar() && isInCleanerEtwasZuBereinigen();
  }

  private boolean isInCleanerEtwasZuBereinigen() {
    var serverVerzeichnis = fileCleanupTransaction.getServerVerzeichnis();
    for (var cleaner : fileCleanerFinder.getFileCleaner()) {
      try {
        var dirtyFilePresent = fileCleanupTransaction.isDirtyFilePresent(cleaner, serverVerzeichnis);
        LOG.info("cleaner = " + cleaner.getName() + ": " + dirtyFilePresent);
        if (dirtyFilePresent) {
          return true;
        }
      } catch (EntityNotFoundException enf) {
        LOG.warn("EntityNotFoundException: " + enf.getMessage());
      } catch (Exception e) {
        systemLogWriter.writeErrorLogMessageFuerSystemMandant("Filecleanup - todo check failed, cleaner: " + cleaner, e, SystemLogQuelle.FILE_CLEANUP);
        // ELECTKOM-2576 nicht abbrechen throw new RuntimeException(cleaner.getName() + "-" + e.getMessage(), e);
      }
    }
    return false;
  }

  public void bereinige() {
    if (fileCleanupTransaction.isDateibereinugungAktiviert()) {
      LOG.info("Starte Dateibereinigung");
      for (var cleaner : fileCleanerFinder.getFileCleaner()) {
        try {
          var buckets = getBuckets(cleaner);
          if (!buckets.isEmpty()) {
            for (var bucket : buckets) {
              try {
                fileCleanupTransaction.bereinige(cleaner, bucket);
              } catch (EntityNotFoundException nfe) {
                LOG.warn("EntityNotFoundException: " + nfe.getMessage() + ", Cleaner: " + cleaner.getName() + ", bucket: " + bucket);
              } catch (Exception e) {
                throw new RuntimeException(cleaner.getName() + " - bucket:" + bucket + ", " + e.getMessage(), e);
              }
            }
            fileCleanupTransaction.cacheLoeschen();
          }
        } catch (Exception e) {
          throw new RuntimeException(cleaner.getName() + ", " + e.getMessage(), e);
        }
      }
      LOG.info("Dateibereinigung Beendet");
    }
  }

  @Nonnull
  private List<? extends FileCleanerBucket<?>> getBuckets(FileCleaner<?> cleaner) throws Exception {
    try {
      LOG.info("Cleaner: " + cleaner.getName() + "; get buckets");
      var buckets = fileCleanupTransaction.getBuckets(cleaner);
      LOG.info("Cleaner: " + cleaner.getName() + "; buckets: " + buckets.size());
      return buckets;
    } catch (Exception e) {
      systemLogWriter.writeErrorLogMessageFuerSystemMandant("Filecleanup - getBuckets failed, cleaner: " + cleaner, e, SystemLogQuelle.FILE_CLEANUP);
      return Collections.emptyList(); // ELECTKOM-2576 nicht abbrechen, erstmal weitermachen
    }
  }

}
