package org.slc.sli.ingestion.handler;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

import javax.xml.transform.stream.StreamSource;

import org.apache.commons.io.IOUtils;
import org.milyn.Smooks;
import org.milyn.SmooksException;
import org.slc.sli.ingestion.NeutralRecordFileWriter;
import org.slc.sli.ingestion.landingzone.IngestionFileEntry;
import org.slc.sli.ingestion.smooks.SliSmooksFactory;
import org.slc.sli.ingestion.validation.ErrorReport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.xml.sax.SAXException;

/**
 * smooks handler for edfi files
 *
 * @author dduran
 *
 */
@Component
public class SmooksFileHandler extends AbstractIngestionHandler<IngestionFileEntry, IngestionFileEntry> {

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

    private SliSmooksFactory sliSmooksFactory;
    
    @Value("${landingzone.inbounddir}")
    private String directory;

    @Override
    IngestionFileEntry doHandling(IngestionFileEntry fileEntry, ErrorReport errorReport) {
        try {

            generateNeutralRecord(fileEntry, errorReport);

        } catch (IOException e) {
            LOG.error("IOException", e);
            errorReport.fatal("Could not instantiate smooks, unable to read configuration file.",
                    SmooksFileHandler.class);
        } catch (SAXException e) {
            errorReport.fatal("Could not instantiate smooks, problem parsing configuration file.",
                    SmooksFileHandler.class);
        }

        return fileEntry;
    }

    void generateNeutralRecord(IngestionFileEntry fileEntry, ErrorReport errorReport) throws IOException, SAXException {

        File neutralRecordOutFile = createTempFile();

        NeutralRecordFileWriter nrFileWriter = new NeutralRecordFileWriter(neutralRecordOutFile);

        // create instance of Smooks (with visitors already added)
        Smooks smooks = sliSmooksFactory.createInstance(fileEntry.getFileType(), nrFileWriter, errorReport);

        InputStream inputStream = new BufferedInputStream(new FileInputStream(fileEntry.getFile()));
        try {

            // filter fileEntry inputStream, converting into NeutralRecord entries as we go
            smooks.filterSource(new StreamSource(inputStream));

            // set the IngestionFileEntry NeutralRecord file we just wrote
            fileEntry.setNeutralRecordFile(neutralRecordOutFile);

        } catch (SmooksException se) {
            LOG.error("smooks exception encountered:\n" + Arrays.toString(se.getStackTrace()));
            errorReport.error("SmooksException encountered while filtering input.", SmooksFileHandler.class);
        } finally {
            IOUtils.closeQuietly(inputStream);
            nrFileWriter.close();
        }
    }

    private File createTempFile() throws IOException {
        File outputFile = File.createTempFile("camel_", ".tmp", new File(directory));
        return outputFile;
    }

    public void setSliSmooksFactory(SliSmooksFactory sliSmooksFactory) {
        this.sliSmooksFactory = sliSmooksFactory;
    }

}

@@ -873,17 +873,18 @@
 files%0A *
+ 
 %0A
-
  * @auth
@@ -895,16 +895,17 @@
 duran%0A *
+ 
 %0A */%0A@Co
@@ -1018,17 +1018,21 @@
 ntry%3E %7B%0A
+    
 %0A
-
     priv
@@ -1111,17 +1111,21 @@
 class);%0A
+    
 %0A
-
     priv
@@ -1227,17 +1227,19 @@
  String 
-d
+lzD
 irectory
@@ -1240,16 +1240,20 @@
 ectory;%0A
+    
 %0A    @Ov
@@ -1356,33 +1356,45 @@
 %7B%0A        try %7B%0A
+            
 %0A
-
             gene
@@ -1428,33 +1428,45 @@
 , errorReport);%0A
+            
 %0A
-
         %7D catch 
@@ -1854,25 +1854,33 @@
 ;%0A        %7D%0A
+        
 %0A
-
         retu
@@ -1895,25 +1895,29 @@
 ntry;%0A    %7D%0A
+    
 %0A
-
     void gen
@@ -2025,17 +2025,25 @@
 ption %7B%0A
+        
 %0A
-
         
@@ -2088,17 +2088,25 @@
 File();%0A
+        
 %0A
-
         
@@ -2187,33 +2187,41 @@
 RecordOutFile);%0A
+        
 %0A
-
         // creat
@@ -2380,17 +2380,25 @@
 eport);%0A
+        
 %0A
-
         
@@ -2504,17 +2504,29 @@
   try %7B%0A
+            
 %0A
-
         
@@ -2673,17 +2673,29 @@
 ream));%0A
+            
 %0A
-
         
@@ -2827,17 +2827,29 @@
 tFile);%0A
+            
 %0A
-
         
@@ -3198,25 +3198,29 @@
     %7D%0A    %7D%0A
+    
 %0A
-
     private 
@@ -3254,32 +3254,82 @@
 s IOException %7B%0A
+        File landingZone = new File(lzDirectory);%0A
         File out
@@ -3337,16 +3337,39 @@
 utFile =
+ landingZone.exists() ?
  File.cr
@@ -3403,27 +3403,75 @@
 p%22, 
-new File(directory)
+landingZone) : File.createTempFile(%22camel_%22,%0A                %22.tmp%22
 );%0A 
@@ -3502,17 +3502,21 @@
 ;%0A    %7D%0A
+    
 %0A
-
     publ
@@ -3636,11 +3636,15 @@
 ;%0A    %7D%0A
+    
 %0A%7D%0A

handle case of landing zone not existing