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

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Date;

import javax.annotation.Nullable;
import javax.inject.Inject;

import org.apache.commons.io.FileExistsException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;

import de.ivu.elect.business.datei.control.FileExchangeDirectory;
import de.ivu.elect.business.datei.entity.Datei;
import de.ivu.elect.business.datei.entity.ServerFileType;
import de.ivu.elect.business.konfiguration.entity.ElectKonfigurationWerte;
import de.ivu.elect.business.konfiguration.entity.KonfigurationLoader;

public abstract class AbstractFileCleanupStrategy implements FileCleanupStrategy {

  private static final String RECYCLE_BIN = "_recycle-bin_";

  @Inject
  protected transient FileExchangeDirectory fileExchangeDirectory;

  @Inject
  protected transient KonfigurationLoader konfigurationLoader;

  protected void verschiebeInRecycleBin(File file, File verzeichnis) throws IOException {
    String name = file.getName();
    if (isMoveToRecycleBinActivated()) {
      try {
        if (!file.setLastModified(new Date().getTime())) {
          getLog().info("lastModified failed: " + file);
        }
        moveFile(file, getRecyclebin(verzeichnis));
      } catch (FileExistsException e) {
        // ELECT-6572
        String nameAlternative = name + "_" + System.currentTimeMillis();
        getLog().warn("Datei in Papierkorb schon vorhanden: " + name + ", neuer Name: " + nameAlternative);
        moveFile(file, new File(getRecyclebin(verzeichnis).getAbsolutePath() + File.separator + nameAlternative));
      }
      getLog().info("Datei keine Entität zugeordnet -> in Papierkorb verschoben: " + name);
    } else {
      Files.deleteIfExists(file.toPath());
      getLog().info("Datei keine Entität zugeordnet -> gelöscht: " + name);
    }
  }

  private void moveFile(File file, File targetDir) throws IOException {
    try {
      getLog().info("Verschiebe Datei: " + file.getName() + ", nach " + targetDir);
      FileUtils.moveFileToDirectory(file, targetDir, true);
    } catch (FileNotFoundException fileNotFoundException) {
      // ELECT-12817 wahrscheinlich schon gelöscht...
      getLog().warn("Datei nicht mehr vorhanden: " + file);
    }
  }

  public static File getRecyclebin(File verzeichnis) {
    return new File(verzeichnis, RECYCLE_BIN);
  }

  protected void verschiebe(File file, File verzeichnis, String subDir, Datei datei) throws IOException {
    moveFile(file, new File(verzeichnis.getAbsoluteFile() + File.separator + subDir));
    datei.setPfad(subDir);
  }

  protected abstract Logger getLog();

  protected String bestimmePfad(Datei datei, ServerFileType serverFileType) {
    return fileExchangeDirectory.erstellePfad(datei, serverFileType);
  }

  protected boolean isInRecycleBin(File file) {
    return file.getAbsolutePath().contains(RECYCLE_BIN);
  }

  private boolean isMoveToRecycleBinActivated() {
    Integer daysInRecycleBin = getDaysInRecycleBin();
    return daysInRecycleBin == null || daysInRecycleBin > 0;
  }

  @Nullable
  protected Integer getDaysInRecycleBin() {
    String value = konfigurationLoader.resolveStringValue(ElectKonfigurationWerte.ELECT_COMMON_DATEI_CLEANUP_DAYS_IN_RECYCLE_BIN);
    if (StringUtils.isBlank(value)) {
      return null;
    }
    try {
      return Integer.parseInt(value);
    } catch (Exception e) {
      return null;
    }
  }
}
