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

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;

import javax.annotation.Nullable;

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

import de.ivu.elect.business.konfiguration.entity.InputStreamMitGroesse;
import de.ivu.elect.jee.exception.ElectCommonException;

public abstract class AbstractStreamCreator implements StreamCreator {

  private static final long serialVersionUID = 1L;

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

  private static final int READ_BUFFER_SIZE = 1024 * 64;

  private static final int WRITE_BUFFER_SIZE = 1024 * 64;

  @Override
  public InputStreamMitGroesse createInputStreamForDatei(String dateiname, @Nullable String path) {
    var absolutePath = getAbsolutePath(dateiname, path);
    try {
      var file = new File(absolutePath);
      var contentLength = getContentLength(file);
      return new InputStreamMitGroesse(new BufferedInputStream(new FileInputStream(file), READ_BUFFER_SIZE), contentLength);
      // return new InputStreamMitGroesse(new FileInputStream(file), contentLength);
    } catch (FileNotFoundException e) {
      LOG.warn(
          "Fehler beim Erstellen eines FileInputStream, dateiname=" + dateiname + ", path=" + path + ", absolutePath=" + absolutePath + ", " + e.getMessage(),
          e);
      throw new ElectCommonException(ElectCommonException.RedirectDestination.NONE /*ELECT-12914 error view zu hässlich*/, "open.file.for.reading.failed", e,
          absolutePath);
    }
  }

  @Nullable
  private Integer getContentLength(File file) {
    try {
      var filesize = file.length();

      Integer contentLength = null;
      if (filesize > 0 && filesize < Integer.MAX_VALUE) {
        contentLength = Math.toIntExact(filesize);
      }
      return contentLength;
    } catch (Exception e) {
      LOG.warn("Fehler beim Bestimmen der Länge: " + e.getMessage());
      return null;
    }
  }

  @Override
  public OutputStream createOutputStreamForDatei(String dateiname, @Nullable String path, boolean append) {
    var absolutePath = getAbsolutePath(dateiname, path);
    try {
      return new BufferedOutputStream(new FileOutputStream(absolutePath, append), WRITE_BUFFER_SIZE);
      // return new FileOutputStream(absolutePath);
    } catch (FileNotFoundException e) {
      LOG.warn(
          "Fehler beim Erstellen eines FileOutputStream, dateiname=" + dateiname + ", path=" + path + ", absolutePath=" + absolutePath + ", " + e.getMessage(),
          e);
      throw new ElectCommonException(ElectCommonException.RedirectDestination.NONE/*ELECT-12914 error view zu hässlich*/, "open.file.for.writing.failed", e,
          absolutePath);
    }
  }

  @Override
  public File createFile(String dateiname, @Nullable String path) {
    return new File(getAbsolutePath(dateiname, path));
  }

  protected abstract String getAbsolutePath(String dateiname, @Nullable String path);

}
