/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package de.nplusc.izc.tools.IOtools.iZformats;

import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import javax.imageio.ImageIO;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import org.yaml.snakeyaml.Yaml;

/**
 *
 * @author LH
 */
public class IZImageGenerated
{
    private int framecount;
    private int width;   //farbtiefe nicht notwending
    private int height;
    private ZipFile backendfile;
    
    private BufferedImage differenceData;
    private BufferedImage baseFrame;
    private String namePattern;
    
    public IZImageGenerated(ZipFile data) throws IOException
    {
        backendfile = data;
        Enumeration<ZipEntry> e = (Enumeration<ZipEntry>) data.entries();
        do{
           ZipEntry etr = e.nextElement();
           String name = etr.getName();
           switch(name)
           {
               case "meta.yml":
                   List mdata = (ArrayList) new Yaml().load(backendfile.getInputStream(etr));
                   framecount=(int) mdata.get(0);
                   height=(int) mdata.get(1);
                   width=(int) mdata.get(2);
                   break;
               case "differences.png":
                   differenceData = ImageIO.read(backendfile.getInputStream(etr));
                   break;
               default:
                   if(!String.format(name,1).equals(name))
                   {
                       namePattern=name;
                       baseFrame = ImageIO.read(backendfile.getInputStream(etr));
                   }
           }
        }
        while(e.hasMoreElements());
    }
    
    public void unpackFrame(int frame,String directory) throws IOException
    {
        BufferedImage it = deepCopy(baseFrame);
        while(it.getHeight()==0);
        int width=it.getWidth();
        int height=it.getHeight();
        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                //System.out.println(">>>"+(differenceData.getRGB(j, i)&0x00FFFFFF));
                if(!((differenceData.getRGB(j, i)&0x00FFFFFF)<=frame))
                {
                    it.setRGB(j, i, 0);
                }
            }
        }
        ImageIO.write(it, "png", new File(directory+"\\"+String.format(namePattern, frame)));
    }
    
    
    
    
    public void unpackAllFrames(String targetDirectory, JProgressBar status, JLabel statusdetail) throws IOException
    {
        if(status!=null)
        {
            status.setMinimum(0);
            status.setMaximum(framecount);
            status.setValue(0);
        }
        if(statusdetail!=null)
        {
            statusdetail.setText("Processing frame 0");
        }
        for (int i = 0; i < framecount; i++)
        {
            if(status!=null)
            {
                status.setValue(i);
            }
            if(statusdetail!=null)
            {
                statusdetail.setText("Processing frame "+i);
            }
            unpackFrame(i, targetDirectory);
        }
    }

    public int getFramecount()
    {
        return framecount;
    }

    public int getWidth()
    {
        return width;
    }

    public int getHeight()
    {
        return height;
    }

    
    
    
    /**
     * 
     * @param directory
     * @param namepattern
     * @param framescount
     * @param status
     * @param statusdetail
     * @return 
     */
    
    public static IZImageGenerated createAndCompress(String targetFilePath,String directory,String namepattern,int framescount, JProgressBar status, JLabel statusdetail) throws IOException
    {
        if(status!=null)
        {
            status.setMinimum(0);
            status.setMaximum(framescount+2);
            status.setValue(0);
        }
        if(statusdetail!=null)
        {
            statusdetail.setText("Loading baseline Image....");
        }
        String[] images = new String[framescount-1];
        String fullimagepath = directory+"\\"+String.format(namepattern, framescount-1);
        for (int i = 0; i < images.length; i++)
        {
            images[i]=directory+"\\"+String.format(namepattern, i);
            
        }
        System.out.println(fullimagepath);
        BufferedImage i = ImageIO.read(new File(fullimagepath));
        while(i.getHeight()==0);
        System.out.println("Loaded baseline");
        if(status!=null)
        {
            status.setValue(1);
        }
        if(statusdetail!=null)
        {
            statusdetail.setText("Pregenerating Datastructures.....");
        }
        BufferedImage diff = new BufferedImage(i.getWidth(), i.getHeight(), BufferedImage.TYPE_INT_RGB);
        while(diff.getHeight()==0);
        System.out.println("Pregenerated Diff...");
        int imagesprocessed=1;
        for (String imgpath : images)
        {
             System.out.println(imgpath);
            //Progressbar stuff
            if(status!=null)
            {
                status.setValue(imagesprocessed+1);
            }
            if(statusdetail!=null)
            {
                statusdetail.setText("Processing Frame "+(imagesprocessed)+" of "+framescount);
                System.out.println("Processing Frame "+(imagesprocessed)+" of "+framescount);
            }
            BufferedImage icomp = ImageIO.read(new File(imgpath));
            while(icomp.getHeight()==0);
            for (int j = 0; j < i.getHeight(); j++)
            {
                for (int k = 0; k < i.getWidth(); k++)
                {
                    if((icomp.getRGB(k, j)!=i.getRGB(k, j))&&diff.getRGB(k, j)!=0)
                    {
                        diff.setRGB(k, j, imagesprocessed);
                    }
                }
            }
            imagesprocessed++;
        }
        
        //Progressbar stuff
        if(status!=null)
        {
            status.setValue(imagesprocessed+1);
        }
        
        if(statusdetail!=null)
        {
            statusdetail.setText("Processing Frame "+(imagesprocessed)+" of "+framescount);
            System.out.println("Processing Frame "+(imagesprocessed)+" of "+framescount);
        }
        ImageIO.write(diff, "png", new File(directory+"\\differences.png"));
        int[] metadata_r= new int[3];
        metadata_r[0]=framescount;
        metadata_r[1]=i.getHeight();
        metadata_r[2]=i.getWidth();
        

        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(targetFilePath)));
        String metadata = new Yaml().dump(metadata_r);
        ZipEntry e = new ZipEntry("meta.yml");
        zos.putNextEntry(e);
        ByteArrayInputStream b = new ByteArrayInputStream(metadata.getBytes());
        byte[] buf = new byte[1024];;
        int len;
        while ((len = b.read(buf)) > 0) {
            zos.write(buf, 0, len);
        }
        zos.closeEntry();
        
        
        e = new ZipEntry("differences.png");
        zos.putNextEntry(e);
        FileInputStream s = new FileInputStream(directory+"\\differences.png");
        
        buf = new byte[1024];;
        while ((len = s.read(buf)) > 0) {
            zos.write(buf, 0, len);
        }
        zos.closeEntry();
        e = new ZipEntry(namepattern);//schema im dateinamen encodieren....
        zos.putNextEntry(e);
        
        s = new FileInputStream(fullimagepath);
        
        buf = new byte[1024];;
        while ((len = s.read(buf)) > 0) {
            zos.write(buf, 0, len);
        }
        zos.closeEntry();
        zos.close();
        ZipFile destination = new ZipFile(targetFilePath);
        if(status!=null)
        {
            status.setValue(status.getValue());
        }
        if(statusdetail!=null)
        {
            statusdetail.setText("Done!");
        }
        return new IZImageGenerated(destination);
        
    }
    
    private static BufferedImage deepCopy(BufferedImage bi) {
    ColorModel cm = bi.getColorModel();
    boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
    WritableRaster raster = bi.copyData(null);
    return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
   }
}


