/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ch.unizh.ini.jaer.projects.davis.frames;

import eu.seebetter.ini.chips.DavisChip;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.beans.PropertyChangeEvent;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sf.jaer.Description;
import net.sf.jaer.DevelopmentStatus;
import net.sf.jaer.chip.AEChip;
import net.sf.jaer.event.EventPacket;
import net.sf.jaer.eventio.AEInputStream;
import net.sf.jaer.eventprocessing.FilterChain;
import net.sf.jaer.graphics.AEFrameChipRenderer;
import net.sf.jaer.util.avioutput.AbstractAviWriter;

/**
 * Writes AVI file from DAVIS APS frames, using ApsFrameExtractor. The AVI file
 * has pixel values 0-255 coming from ApsFrameExtractor
 * displayed frames, which are offset and scaled by it.
 *
 * @author Tobi
 */
@Description("Writes AVI file from DAVIS APS frames, using ApsFrameExtractor. This AVI has spatial resolution the same as the AEChip (not the display resolution)")
@DevelopmentStatus(DevelopmentStatus.Status.Stable)
public class DavisFrameAviWriter extends AbstractAviWriter {

//    ApsFrameExtractor apsFrameExtractor;
    DavisChip apsDvsChip = null;
    private boolean rendererPropertyChangeListenerAdded=false;
    private AEFrameChipRenderer renderer=null;

    public DavisFrameAviWriter(AEChip chip) {
        super(chip);
        FilterChain filterChain = new FilterChain(chip);
//        apsFrameExtractor = new ApsFrameExtractor(chip);
//        apsFrameExtractor.getSupport().addPropertyChangeListener(this);
//        filterChain.add(apsFrameExtractor);
        setEnclosedFilterChain(filterChain);
        setPropertyTooltip("saveAVIFileAs", "Opens the output file. The AVI file is in RAW format with pixel values 0-255 coming from ApsFrameExtractor displayed frames, which are offset and scaled by it.");
        setPropertyTooltip("closeFile", "Closes the output file if it is open.");
        setPropertyTooltip("writeTimecodeFile", "writes a file alongside AVI file (with suffix " + TIMECODE_SUFFIX + ") that maps from AVI frame to AER timestamp for that frame (the frame end timestamp)");
        setPropertyTooltip("closeOnRewind", "closes recording on rewind event, to allow unattended operation");
    }

    @Override
    synchronized public EventPacket<?> filterPacket(EventPacket<?> in) {
        super.filterPacket(in); // adds propertychangelistener for rewind event
        if(!rendererPropertyChangeListenerAdded){
            rendererPropertyChangeListenerAdded=true;
            renderer=(AEFrameChipRenderer)chip.getRenderer();
            renderer.getSupport().addPropertyChangeListener(this);
        }
        apsDvsChip = (DavisChip) chip;
//        apsFrameExtractor.filterPacket(in);
        return in;
    }

//    @Override
//    public void resetFilter() {
//        apsFrameExtractor.resetFilter();
//    }
//
//    @Override
//    public void initFilter() {
//        apsFrameExtractor.initFilter();
//    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if (aviOutputStream != null && evt.getPropertyName() == AEFrameChipRenderer.EVENT_NEW_FRAME_AVAILBLE) {
            FloatBuffer frame = ((AEFrameChipRenderer)chip.getRenderer()).getPixBuffer();

            BufferedImage bufferedImage = new BufferedImage(chip.getSizeX(), chip.getSizeY(), BufferedImage.TYPE_3BYTE_BGR);
            WritableRaster raster = bufferedImage.getRaster();
            int sx = chip.getSizeX(), sy = chip.getSizeY();
            for (int y = 0; y < sy; y++) {
                for (int x = 0; x < sx; x++) {
                    int k = renderer.getPixMapIndex(x, y);
//                    bufferedImage.setRGB(x, y, (int) (frame[k] * 1024));
                    int yy=yy = sy - y - 1;
                    int r = (int) (frame.get(k) * 255); // must flip image vertially according to java convention that image starts at upper left
                    int g = (int) (frame.get(k+1) * 255); // must flip image vertially according to java convention that image starts at upper left
                    int b = (int) (frame.get(k+2) * 255); // must flip image vertially according to java convention that image starts at upper left
                    raster.setSample(x, yy, 0, r);
                    raster.setSample(x, yy, 1, g);
                    raster.setSample(x, yy, 2, b);
                }
            }
            try {
                aviOutputStream.writeFrame(bufferedImage);
                int timestamp = renderer.getTimestampFrameEnd();
                writeTimecode(timestamp);
                incrementFramecountAndMaybeCloseOutput();

            } catch (IOException ex) {
                Logger.getLogger(DavisFrameAviWriter.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else if (evt.getPropertyName() == AEInputStream.EVENT_REWIND) {
            doCloseFile();
        }
    }

}

@@ -239,50 +239,8 @@
 %0D%0A%0D%0A
-import eu.seebetter.ini.chips.DavisChip;%0D%0A
 impo
@@ -474,24 +474,26 @@
 ng.Logger;%0D%0A
+%0D%0A
 import net.s
@@ -819,16 +819,58 @@
 Writer;%0D
+%0Aimport eu.seebetter.ini.chips.DavisChip;%0D
 %0A%0D%0A/**%0D%0A
@@ -3373,16 +3373,17 @@
      if 
+(
 (aviOutp
@@ -3402,12 +3402,14 @@
 null
+)
  && 
+(
 evt.
@@ -3474,16 +3474,17 @@
 VAILBLE)
+)
  %7B%0D%0A    
@@ -4081,11 +4081,8 @@
 t yy
-=yy
  = s

remove double-assignment to same variable.