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

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import javax.inject.Inject;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;

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

import de.ivu.elect.business.datei.boundary.DateiDAO;
import de.ivu.elect.business.datei.boundary.DateiExportDAO;
import de.ivu.elect.business.datei.boundary.DateiImportDAO;
import de.ivu.elect.business.datei.entity.Datei;
import de.ivu.elect.business.datei.entity.DateiExport;
import de.ivu.elect.business.datei.entity.DateiImport;
import de.ivu.elect.business.datei.entity.ServerFileType;

/**
 * Teilt bestehende Dateien nach dem "neuen" Ablagemuster pro Wahl auf
 */
public class DateiDirektInAblageverzeichnisFileCleanupStrategy extends AbstractFileCleanupStrategy implements FileCleanupStrategy {

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

  @Inject
  private transient DateiDAO dateiDAO;

  @Inject
  private transient DateiImportDAO dateiImportDAO;

  @Inject
  private transient DateiExportDAO dateiExportDAO;

  @Override
  public boolean isDirtyFilePresent(File verzeichnis) {
    return isDateiDirektInServerVerzeichnis(verzeichnis);
  }

  @Override
  public void bereinige(File verzeichnis) throws Exception {

    File file = getErsteDateiDirektInServerVerzeichnis(verzeichnis);

    if (file != null) {
      String name = file.getName();
      LOG.info("Datei zum Bereinigen direkt in Ablageverzeichnis gefunden: " + name);
      List<Datei> dateien = dateiDAO.findByDateinamePfadNull(name);
      if (dateien.isEmpty()) {
        verschiebeInRecycleBin(file, verzeichnis);
      } else {
        Datei datei = dateien.get(0);
        DateiExport dateiExport = findeDateiExport(datei);
        if (dateiExport != null) {
          verschiebeInExportVerzeichnis(file, verzeichnis, dateiExport);
        } else {
          DateiImport dateiImport = findeDateiImport(datei);
          if (dateiImport != null) {
            verschiebeInImportVerzeichnis(file, verzeichnis, dateiImport);
          } else {
            verschiebeInLegacyVerzeichnis(file, verzeichnis, datei);
          }
        }
      }
    }
  }

  @Override
  public String getName() {
    return DateiDirektInAblageverzeichnisFileCleanupStrategy.class.getName();
  }

  private void verschiebeInLegacyVerzeichnis(File file, File verzeichnis, Datei datei) throws IOException {
    verschiebe(file, verzeichnis, bestimmePfad(datei, ServerFileType.LEGACY), datei);
  }

  private void verschiebeInImportVerzeichnis(File file, File verzeichnis, DateiImport dateiImport) throws IOException {
    verschiebe(file, verzeichnis, bestimmePfad(dateiImport.getDatei(), dateiImport.getDateiArt().getServerFileType()), dateiImport.getDatei());
  }

  private void verschiebeInExportVerzeichnis(File file, File verzeichnis, DateiExport dateiExport) throws IOException {
    verschiebe(file, verzeichnis, bestimmePfad(dateiExport.getDatei(), dateiExport.getDateiArt().getServerFileType()), dateiExport.getDatei());
  }

  private DateiImport findeDateiImport(Datei datei) {
    try {
      return dateiImportDAO.findByDatei(datei);
    } catch (NoResultException | NonUniqueResultException e) {
      return null;
    }
  }

  private DateiExport findeDateiExport(Datei datei) {
    try {
      return dateiExportDAO.findByDatei(datei);
    } catch (NoResultException | NonUniqueResultException e) {
      return null;
    }
  }

  private boolean isDateiDirektInServerVerzeichnis(File verzeichnis) {
    return getErsteDateiDirektInServerVerzeichnis(verzeichnis) != null;
  }

  private File getErsteDateiDirektInServerVerzeichnis(File verzeichnis) {
    File[] files = verzeichnis.listFiles();
    if (files != null) {
      return Arrays.stream(files).filter(File::isFile).findFirst().orElse(null);
    }
    return null;
  }

  @Override
  protected Logger getLog() {
    return LOG;
  }
}
