
package de.ivu.elect.presentation.email;

import static java.util.Arrays.asList;
import static org.apache.commons.lang3.StringUtils.isBlank;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.persistence.NoResultException;

import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
import org.primefaces.model.file.UploadedFile;

import de.ivu.elect.business.datei.entity.DateiExport;
import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.datei.entity.FileTypeResolver;
import de.ivu.elect.business.email.boundary.CommonEmailVorgangBoundaryCreate;
import de.ivu.elect.business.email.entity.AbstractEmailVorgang;
import de.ivu.elect.business.email.entity.EmailVorgang;
import de.ivu.elect.business.email.entity.EmailVorgangPlatzhalter;
import de.ivu.elect.business.exchange.control.ImportExportStreamCreator;
import de.ivu.elect.business.konfiguration.entity.KonfigurationExtendedLoader;
import de.ivu.elect.business.konfiguration.entity.MandantKonfigurationWerte;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.UseCaseSecure;
import de.ivu.elect.business.wahl.boundary.WahlterminNichtAusgewaehltException;
import de.ivu.elect.jee.faces.PreConditionCheck;
import de.ivu.elect.jee.faces.upload.UploadedFileWithCanonicalFilename;
import de.ivu.elect.jee.presentation.dynamicform.FormBuilder;
import de.ivu.elect.jee.presentation.redirect.Redirect;
import de.ivu.elect.presentation.email.form.EmailVorgangViewFormBuilder;
import de.ivu.elect.presentation.person.PersonendatenFormatter;

public abstract class AbstractEmailVorgangCreateView extends AbstractEmailVorgangCreateNoScopeView implements EmailDateiAnhaengeView {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient FileTypeResolver fileTypeResolver;

  @Inject
  private transient CommonEmailVorgangBoundaryCreate create;

  @Inject
  private transient EmailVorgangViewFormBuilder emailVorgangViewFormBuilder;

  @Inject
  private transient PersonendatenFormatter personendatenFormatter;

  @Inject
  private transient KonfigurationExtendedLoader konfigurationExtendedLoader;

  @Inject
  private transient ImportExportStreamCreator streamCreator;

  public AbstractEmailVorgangCreateView() {
    super();
  }

  @Override
  @PostConstruct
  public void init() {
    super.init();

    getEntity().setInhalt(AbstractEmailVorgang.getInhaltDefaultValue());
  }

  @PreConditionCheck
  public String checkPreCondition() {
    if (!isWahlterminSelected() && !isWahlSelected()) {
      throw new WahlterminNichtAusgewaehltException();
    }

    if (!isMailServiceEnabled()) {
      addWarningMessage("interfaces.email.test.status.deaktiviert");
    }

    return null;
  }

  private boolean isMailServiceEnabled() {
    boolean mailServiceEnabled = false;

    try {
      mailServiceEnabled = konfigurationExtendedLoader.resolveBooleanValue(getMandant(), MandantKonfigurationWerte.MAIL_SERVICE_ENABLED);
    } catch (NoResultException e) {
      // do nothing
    }

    return mailServiceEnabled;
  }

  @Override
  @Redirect
  @UseCaseSecure(UseCasePermission.EMAIL_VORGANG_CREATE)
  public String save() {
    checkPreCondition();

    if (!isValid(getEntity())) {
      return getViewId();
    }

    try {
      create.save(getEntity(), getSelectedWahl(), getSelectedWahltermin(), getSelectedBenutzer());

      addMessageSaveSuccess(getEntity());

      onClose();
      resetStateAfterAction();

    } catch (IOException e) {
      addErrorMessage(e);
      return getViewId();
    }

    return goBack(getParentViewId());
  }

  private boolean isValid(EmailVorgang emailVorgang) {
    boolean result = true;

    if (isBlank(emailVorgang.getBetreff())) {
      result = false;
      addErrorMessage("email.vorgang.create.betreff.leer.error.message");
    }

    if (isBlank(emailVorgang.getInhalt())) {
      result = false;
      addErrorMessage("email.vorgang.create.inhalt.leer.error.message");
    }

    return result;
  }

  @Override
  @Redirect
  public String cancel() {
    onClose();

    return super.cancel();
  }

  protected abstract void onClose();

  @Override
  protected void addProperties(FormBuilder formBuilder, EmailVorgang emailVorgang) {
    checkPreCondition();

    emailVorgangViewFormBuilder.addEmailVorgangProperties(formBuilder, emailVorgang);
  }

  @Override
  public String getBtnSaveLabel() {
    return getMessage("email.vorgang.create.action.senden");
  }

  protected void ersetzePlatzhalterWennNurEinEmpfaenger() {
    String inhaltDefaultValue = getEntity().getInhalt();

    if (getEntity().getAnzahlEmpfaengerPersonendaten() == 1) {
      inhaltDefaultValue = EmailVorgangPlatzhalter.ersetzeAllePlatzhalter(inhaltDefaultValue, getEntity().getEmpfaengerPersonendaten().get(0), personendatenFormatter);
    }

    getEntity().setInhalt(inhaltDefaultValue);
  }

  @Override
  public boolean isBtnFileUploadDisabled() {
    return !isBtnSaveRendered();
  }

  @Override
  public void handleFileUpload(FileUploadEvent event) {
    UploadedFile uploadedFile = new UploadedFileWithCanonicalFilename(event.getFile());

    if (uploadedFile != null) {
      if (getEntity().hatAnhangMitGleichemDateiname(uploadedFile)) {
        addInfoMessage("email.vorgang.create.info.anhang.ersetzt");
      }

      getEntity().addUploadedFile(uploadedFile);
    }
  }

  @Override
  public String getFileUploadLabel() {
    return getMessage("email.vorgang.create.upload.action.choose", fileTypeResolver.formatFileTypes(getFileUploadFileTypes()));
  }

  @Override
  public String getFileUploadAllowTypes() {
    return FILE_UPLOAD_ALLOW_TYPES_ALL;
  }

  @Override
  public String getFileUploadAccept() {
    return fileTypeResolver.getFileTypesHtmlAccept(getFileUploadFileTypes());
  }

  @Override
  public List<FileType> getFileUploadFileTypes() {
    return asList(FileType.ALL);
  }

  @Override
  public List<String> getAnhaengeDateinamen() {
    return getEntity().getAnhaengeDateinamen();
  }

  @Override
  public void removeAnhang(String dateiname) {
    getEntity().removeAnhang(dateiname);
  }

  @Override
  public StreamedContent downloadAnhang(String dateiname) {
    UploadedFile uploadedFile = getEntity().getFileUploadByDateiname(dateiname);

    if (uploadedFile != null) {
      try {
        InputStream inputStream = uploadedFile.getInputStream();
        return DefaultStreamedContent.builder()
            .stream(() -> inputStream)
            .contentType(uploadedFile.getContentType())
            .build();
      } catch (IOException e) {
        addErrorMessage(e);
      }
    }

    DateiExport dateiExport = getEntity().getDateiExportByDateiname(dateiname);

    if (dateiExport != null) {
      return dateiExport.getDatei().getDefaultStreamedContent(streamCreator);
    }

    return null;
  }
}
