
package de.ivu.elect.jee.presentation.pdf;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.ref.SoftReference;

import javax.enterprise.context.SessionScoped;
import javax.inject.Named;

import org.apache.commons.io.IOUtils;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;

/**
 * ELECT-5412
 *
 * @GroupedConversationScoped funktioniert nicht wegen ELECT-5412
 * @ConversationScoped verliert die gespeicherten Informationen => SessionScope
 */
@SessionScoped
@Named("mediaStore")
public class MediaStore implements Serializable {

  private static final long serialVersionUID = 1L;

  private static final int BUFFER_SIZE_IN_BYTES = 1024 * 10; // 10 KiB

  private String name;

  private String contentType;

  private transient SoftReference<byte[]> content; // Byte Arrays in der Session speichern ist nicht die beste Idee => OOME verhindern

  public MediaStore() {
    super();
  }

  public void storePdf(String name, InputStream content) {
    storeMedia(name, "application/pdf", content);
  }

  public void storeMedia(String name, String contentType, InputStream content) {
    try {
      ByteArrayOutputStream bos = new ByteArrayOutputStream(BUFFER_SIZE_IN_BYTES);
      IOUtils.copy(content, bos);
      storeMedia(name, contentType, bos.toByteArray());
    } catch (IOException e) {
      throw new RuntimeException(e.getMessage(), e);
    }
  }

  public void storeMedia(String name, String contentType, byte[] content) {
    this.name = name;
    this.contentType = contentType;
    this.content = new SoftReference(content);
  }

  public void clear() {
    name = null;
    contentType = null;
    content = null;
  }

  public StreamedContent getMedia() throws FileNotFoundException {
    byte[] contentBytes = null;
    if (content != null) {
      contentBytes = content.get();
    }
    if (contentBytes == null) {
      contentBytes = new byte[0];
    }

    final byte[] finalContentBytes = contentBytes;
    return DefaultStreamedContent.builder()
        .stream(() -> new ByteArrayInputStream(finalContentBytes))
        .contentType(contentType)
        .name(name)
        .build();
  }

}
