package de.ivu.elect.presentation.system;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

import javax.annotation.Nullable;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;

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

import de.ivu.elect.business.konfiguration.entity.CustomParameterKategorie;
import de.ivu.elect.business.konfiguration.entity.ElectKonfigurationWerte;
import de.ivu.elect.business.konfiguration.entity.Konfiguration;
import de.ivu.elect.business.konfiguration.entity.KonfigurationExtendedLoader;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.UseCaseSecure;
import de.ivu.elect.business.system.control.files.FileCleanupEvent;
import de.ivu.elect.business.system.control.files.strategies.AbstractFileCleanupStrategy;
import de.ivu.elect.jee.presentation.dynamicform.AdvancedDynaFormModel;
import de.ivu.elect.jee.presentation.dynamicform.DynamicFormEditOrCreateView;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.dynamicform.ReadOnlyLongProperty;
import de.ivu.elect.jee.presentation.dynamicform.ReadOnlyStringProperty;
import de.ivu.elect.jee.presentation.redirect.Redirect;
import de.ivu.elect.presentation.AbstractElectView;
import de.ivu.elect.presentation.View;
import de.ivu.elect.presentation.hilfe.OnlineHilfeId;
import de.ivu.elect.presentation.konfiguration.form.CustomParameterViewFormBuilder;
import de.ivu.elect.util.FileUtil;

@RequestScoped
@Named(DateiStatusuebersichtView.COMPONENT_NAME)
@View(viewId = DateiStatusuebersichtView.VIEW_ID, useCase = UseCasePermission.DATEI_STATUSUEBERSICHT_ANZEIGEN)
@OnlineHilfeId("789")
public class DateiStatusuebersichtView extends AbstractElectView implements DynamicFormEditOrCreateView {

  public static final String COMPONENT_NAME = "dateiStatusuebersichtView";

  public static final String VIEW_ID = "/system/datei-statusuebersicht.xhtml";

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

  private static final long serialVersionUID = 1L;

  private AdvancedDynaFormModel model = null;

  @Inject
  private transient KonfigurationExtendedLoader konfigurationExtendedLoader;

  @Inject
  private transient FileCleanupEvent fileCleanupEvent;

  @Inject
  private transient CustomParameterViewFormBuilder customParameterViewFormBuilder;


  @Override
  public AdvancedDynaFormModel getModel() {
    if (model == null) {
      checkKonfiguration();
      FormBuilder formBuilder = new FormBuilder();


      formBuilder.addSeparator("datei.uebersicht.dateibereinigung");

      for (ElectKonfigurationWerte electKonfigurationWerte : ElectKonfigurationWerte.values()) {
        if (CustomParameterKategorie.DATEI_CLEANUP.equals(electKonfigurationWerte.getKategorie())) {
          Konfiguration konfiguration = konfigurationExtendedLoader.getParameter(electKonfigurationWerte);
          customParameterViewFormBuilder.addProperty(formBuilder, konfiguration, konfiguration.getProperties().getWertProperty(), UseCasePermission.KONFIGURATION_EDIT_SECRETS_CLEAR_TEXT, konfiguration.getKurzname(getMessages()),
              konfiguration.getBeschreibung(getMessages()));
          formBuilder.withReadonly(true);
        }
      }

      formBuilder.addSeparator("datei.uebersicht.ablageverzeichnis");
      String verzeichnis = getAblageverzeichnis();
      formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("datei.uebersicht.ablageverzeichnis.pfad"), verzeichnis));
      if (StringUtils.isNotBlank(verzeichnis)) {
        File dir = new File(verzeichnis);
        if (dir.isDirectory()) {
          File recylebin = getRecycleBinDir(verzeichnis);
          String reclybinPath = null;
          if (recylebin != null && recylebin.isDirectory()) {
            reclybinPath = recylebin.getAbsolutePath();
          }
          try {
            AtomicLong anzahlDateienInsgesamt = new AtomicLong(0L);
            AtomicLong sizeDateienInsgesamt = new AtomicLong(0L);
            AtomicLong anzahlDateienPapierkorb = new AtomicLong(0L);
            AtomicLong sizeDateienpapierkorb = new AtomicLong(0L);

            List<File> files = FileUtil.listFilesInDirectoryFast(dir, true);
            LOG.info("Analysiere Dateien");
            for (File file : files) {
              long filesize = file.length();
              anzahlDateienInsgesamt.incrementAndGet();
              sizeDateienInsgesamt.getAndAdd(filesize);
              if (reclybinPath != null && file.getAbsolutePath().startsWith(reclybinPath)) {
                anzahlDateienPapierkorb.incrementAndGet();
                sizeDateienpapierkorb.getAndAdd(filesize);
              }
            }
            LOG.info("Analysiere Dateien - done");
            formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("datei.uebersicht.ablageverzeichnis.anzahl"), anzahlDateienInsgesamt.longValue()));
            formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("datei.uebersicht.ablageverzeichnis.size"), sizeDateienInsgesamt.longValue()));

            formBuilder.addSeparator("datei.uebersicht.papierkorb");
            if (recylebin != null) {
              formBuilder.addProperty(new ReadOnlyStringProperty(getMessage("datei.uebersicht.papierkorb.pfad"), recylebin.getAbsolutePath()));
            }
            formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("datei.uebersicht.papierkorb.anzahl"), anzahlDateienPapierkorb.longValue()));
            formBuilder.addProperty(new ReadOnlyLongProperty(getMessage("datei.uebersicht.papierkorb.size"), sizeDateienpapierkorb.longValue()));

          } catch (IOException e) {
            LOG.warn("Fehler beim Lesen von Dateien in Verzeichnis: " + dir + ", " + e.getMessage(), e);
          }
        }
      }

      model = formBuilder.createModel();
    }

    return model;
  }

  private void checkKonfiguration() {
    checkKonfiguration(ElectKonfigurationWerte.ELECT_COMMON_DATEI_CLEANUP_MAX_EXPORT_COUNT);
    checkKonfiguration(ElectKonfigurationWerte.ELECT_COMMON_DATEI_CLEANUP_MAX_IMPORT_COUNT);
  }

  private void checkKonfiguration(ElectKonfigurationWerte konfigurationWerte) {
    if (StringUtils.isBlank(konfigurationExtendedLoader.resolveStringValue(konfigurationWerte))) {
      addWarningMessage("datei.statusuebersicht.konfiguration.nicht.gesetzt", getMessage(konfigurationWerte));
    }
  }

  @Nullable
  private File getRecycleBinDir(String ablageverzeichnis) {
    if (StringUtils.isBlank(ablageverzeichnis)) {
      return null;
    }
    return AbstractFileCleanupStrategy.getRecyclebin(new File(ablageverzeichnis));
  }

  private String getAblageverzeichnis() {
    return konfigurationExtendedLoader.resolveStringValue(ElectKonfigurationWerte.ELECT_COMMON_DATEI_ABLAGE_VERZEICHNIS_PFAD);
  }

  public boolean isBtnCleanupRendered() {
    return principal.hasUseCasePermission(UseCasePermission.DATEIEN_BEREINIGEN);
  }

  public boolean isBtnCleanupDisabled() {
    return false;
  }

  @Redirect
  @UseCaseSecure(UseCasePermission.DATEIEN_BEREINIGEN)
  public String cleanup() {
    model = null;
    fileCleanupEvent.sendChangeEvent();
    addInfoMessage("datei.statusuebersicht.cleanup.success");
    return VIEW_ID;
  }

  public boolean isBtnPapierkorbLoeschenRendered() {
    return principal.hasUseCasePermission(UseCasePermission.PAPIERKORB_LEEREN);
  }

  public boolean isBtnPapierkorbLoeschenDisabled() {
    File recycleBinDir = getRecycleBinDir(getAblageverzeichnis());
    return recycleBinDir == null || !recycleBinDir.isDirectory();
  }

  @Redirect
  @UseCaseSecure(UseCasePermission.PAPIERKORB_LEEREN)
  public String papierkorbLoeschen() {
    model = null;
    File recycleBinDir = getRecycleBinDir(getAblageverzeichnis());
    if (recycleBinDir != null && recycleBinDir.isDirectory()) {
      try {
        FileUtils.deleteDirectory(recycleBinDir);
        addInfoMessage("datei.statusuebersicht.papierkorb.loeschen.success");
      } catch (IOException e) {
        LOG.warn("Fehler beim Löschen des Papierkorbs: " + recycleBinDir + ", " + e.getMessage(), e);
        addErrorMessage("datei.statusuebersicht.papierkorb.loeschen.fehler", e.getMessage());
      }
    } else {
      addWarningMessage("datei.statusuebersicht.papierkorb.loeschen.nicht.moeglich");
    }
    return VIEW_ID;
  }

  @Override
  public String getBtnSaveLabel() {
    return null;
  }

  @Override
  public boolean isBtnSaveRendered() {
    return false;
  }

  @Override
  public String save() {
    return null;
  }

  @Override
  public boolean isBtnResetRendered() {
    return false;
  }

  @Override
  public String reset() {
    return null;
  }

  @Override
  public boolean isBtnCancelRendered() {
    return false;
  }

  @Override
  public String cancel() {
    return null;
  }
}
