
package de.ivu.elect.exchange.csv;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.inject.Inject;

import de.ivu.elect.business.exchange.control.FileKonfiguration;

public class CsvMarshaller {

  @Inject
  private transient ElectCsvHeaderExtractor csvHeaderExtractor;

  public CsvMarshaller() {
    super();
  }

  public List<String> extractHeader(Class< ? > clazz) {
    return csvHeaderExtractor.extractHeader(clazz);
  }

  public <T> void serialize(Class<T> clazz, List<T> objects, OutputStream os, FileKonfiguration fileKonfiguration) {
    serialize(clazz, objects, os, createCsvDescriptor(fileKonfiguration));
  }

  public <T> void serialize(Class<T> clazz, List<T> objects, OutputStream os, FileKonfiguration fileKonfiguration, boolean closeOutputStream) {
    serialize(clazz, objects, os, createCsvDescriptor(fileKonfiguration), closeOutputStream);
  }

  public <T> void serialize(Class<T> clazz, List<T> objects, OutputStream os, CsvDescriptor csvDescriptor) {
    serialize(clazz, objects, os, csvDescriptor, true);
  }

  public <T> void serialize(Class<T> clazz, List<T> objects, OutputStream os, CsvDescriptor csvDescriptor, boolean closeOutputStream) {
    serializeIntern(clazz, objects, os, csvDescriptor, closeOutputStream);
  }

  private <T> void serializeIntern(Class<T> clazz, List<T> objects, OutputStream os, CsvDescriptor csvDescriptor, boolean closeOutputStream) {
    try (AutoCloseableCsvSerializer<T> serializer = new AutoCloseableCsvSerializer<>(clazz, os, csvDescriptor, closeOutputStream)) {
      for (T object : objects) {
        serializer.write(object);
      }
    }
  }

  public <T> List<T> deserialize(Class<T> clazz, InputStream is, FileKonfiguration fileKonfiguration) {
    return deserialize(clazz, is, createCsvDescriptor(fileKonfiguration));
  }

  public <T> List<T> deserialize(Class<T> clazz, InputStream is, CsvDescriptor csvDescriptor) {
    List<T> deserialisationResult = new ArrayList<>();

    try (AutoCloseableCsvDeserializer<T> deserializer = new AutoCloseableCsvDeserializer<>(clazz, is, csvDescriptor)) {
      while (deserializer.hasNext()) {
        T csvLine = deserializer.next();

        if (csvLine != null) { // Leerzeilen ignorieren (vgl. ELECT-1079)
          deserialisationResult.add(csvLine);
        }
      }
    }

    return deserialisationResult;
  }

  private CsvDescriptor createCsvDescriptor(FileKonfiguration fileKonfiguration) {
    return CsvDescriptor.forFileKonfiguration(fileKonfiguration);
  }
}
