package de.ivu.elect.business.dokumente.control;

import java.util.List;
import java.util.Optional;

import javax.ejb.Asynchronous;
import javax.ejb.Stateless;
import javax.inject.Inject;

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

import de.ivu.elect.business.dokumente.boundary.DokumentVorlageOpenOfficeTest;
import de.ivu.elect.business.dokumente.boundary.LetzterLibreOfficeStatus;
import de.ivu.elect.business.dokumente.entity.LibreOfficeStatus;
import de.ivu.elect.business.system.boundary.SystemLogWriter;
import de.ivu.elect.business.system.entity.SystemLogQuelle;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.presentation.dokumente.DokumentGenerierenProgressMonitor;

/**
 * ELECT-5970
 */
@Stateless
public class DokumentePostStartupAsync {

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

  @Inject
  private transient BaseOpenOfficeKonfigurationFactory openOfficeDokumentKonfiguration;

  @Inject
  private transient DokumentVorlageOpenOfficeTest dokumentVorlageOpenOfficeTest;

  @Inject
  private transient DokumentGenerierenProgressMonitor dokumentGenerierenProgressMonitor;

  @Inject
  private transient SystemLogWriter systemLogWriter;

  @Inject
  private transient Messages messages;

  @Inject
  private transient LetzterLibreOfficeStatus letzterLibreOfficeStatus;

  @Asynchronous // ELECT-5970
  public void postStartupAsync() {
    if (openOfficeDokumentKonfiguration.isOpenOfficeBeiSystemStartAusfuehren()) {
      if (letzterLibreOfficeStatus.getLibreOfficeStatus().isNichtVerwendet()) {
        letzterLibreOfficeStatus.setLibreOfficeStatus(LibreOfficeStatus.UNBEKANNT);
      }
      if (checkConnection()) {
        LOG.info("Open/LibreOffice erster Start erfolgreich");
      } else {
        LOG.warn("Open/LibreOffice erster Start fehlgeschlagen - wiederhole in einer Minute");
        try {
          Thread.sleep(60000); // ELECT-16005
        } catch (InterruptedException e) {
          throw new RuntimeException(e);
        }

        if (checkConnection()) {
          LOG.info("Open/LibreOffice zweiter Start erfolgreich");
        } else {
          LOG.warn("Open/LibreOffice zweiter Start fehlgeschlagen");
        }
      }
    } else {
      LOG.info("Open/LibreOffice nicht bei Systemstart ausführen");
    }

  }

  private boolean checkConnection() {
    LOG.info("Open/LibreOffice starten");
    try {
      var result = dokumentVorlageOpenOfficeTest.isOpenOfficeAvailable(dokumentGenerierenProgressMonitor);
      if (result.isConnectionPossible() && result.isConversionPossible()) {
        LOG.info("Open/LibreOffice starten - done");
        return true;
      } else {
        LOG.warn("Connection; " + result.isConnectionPossible() + ", konvertierung: " + result.isConversionPossible());
        var message = Optional.ofNullable(result.getThrowable()).map(Throwable::getMessage).orElse(getLastOrNull(result.getMessages()));
        systemLogWriter.writeWarnLogMessageFuerSystemMandant(messages.getMessageForMessageKey("open.office.system.start.fehler", message),
            SystemLogQuelle.SYSTEM);
        LOG.warn("Open/LibreOffice NICHT GESTARTET ODER KONVERTIERUNG NICHT MOEGLICH - FEHLER: " + message);
      }

    } catch (Exception e) {
      LOG.error("Fehler beim Starten von Open/LibreOffice: " + e.getMessage(), e);
    }
    return false;
  }

  @Asynchronous
  public void restartAsync() {
    if (!letzterLibreOfficeStatus.getLibreOfficeStatus().isNichtVerwendet()) {
      letzterLibreOfficeStatus.setLibreOfficeStatus(LibreOfficeStatus.UNBEKANNT);
    }
    dokumentVorlageOpenOfficeTest.shutdown(dokumentGenerierenProgressMonitor);
    postStartupAsync();
  }

  private String getLastOrNull(List<String> messages) {

    if (messages.isEmpty()) {
      return "";
    }
    return messages.get(messages.size() - 1);

  }
}
