/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package csa.tiletools.particle;

import csa.gui.ImageCache;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.HashMap;

/**
 *
 * @author salchr
 */
public class Particle {
    // an Emmitter can be a particel!
    ParticleData config;
    
    public static HashMap<String, HashMap> cachePerId = new HashMap<String, HashMap>();
    int drawMode = ParticleEngine.PARTICLE_TEXTURE; // only TEXTURE as of now

    int height;
    int width; // most often the size of the texture!
    
    float xD; // position of the top/left corner of the particle
    float yD;
    
    float lifeNow; // in ticks - respects tickCount!
    float alphaFadeNow;
    float rotateAngleNow;
    
    int colorNow;
    private BufferedImage orgTexture;
    private String currentKey;

    HashMap<String, BufferedImage> cache;
    
    public static void resetCache()
    {
        cachePerId.clear();
    }
    public static void resetCache(String id)
    {
        HashMap<String, BufferedImage> cache = cachePerId.get(id);
        cache.clear();
        cachePerId.remove(id);
    }
    
    public Particle(ParticleData c)
    {
        // config must be set from outside!
        config = cloneConfig(c);
        init();
    }

    public boolean isActive()
    {
        if (lifeNow<=0) return false;
        return true;
    }

    public boolean update()
    {
        // Movement
//        yD=yD-0.3f;
        yD=yD-config.mStartVelocity1;

        // opacity / Fade
        float opacity = 1.0f;
        if (config.mFade>0)
        {
            alphaFadeNow += config.mFade;
            if (alphaFadeNow > 255) alphaFadeNow = 255;
            if (alphaFadeNow == 255)
            {
                opacity = 0.0f;
                lifeNow = 0;
            }
            else
                opacity = (255.0f-alphaFadeNow)/255.0f;
        }
        
        // Rotation
        rotateAngleNow = (rotateAngleNow + config.mRotate) % 360;

        // Coloring
        // todo calc new colors
        
        // cache stuff
        currentKey = ""+((int)alphaFadeNow)+"_"+colorNow+"_"+((int)rotateAngleNow);
        if (cache.containsKey(currentKey))
        {
            return true;
        }

        // empty image
        BufferedImage usedTexture = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = (Graphics2D) usedTexture.getGraphics();

        // draw org image with opacity settings on empty image
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_ATOP, opacity) ); 
        g2.drawImage(orgTexture, 0, 0, null);
        
        // "reset" composite settings to "normal"
        g2.setComposite(AlphaComposite.SrcOver); 
        
        // if tinting, overlay current image with the color
        if (config.mUseTint)
        {
            g2.setComposite(AlphaComposite.SrcAtop); 
            Color c  = new Color(colorNow);
            g2.setColor(c);
            g2.fillRect(0, 0, width, height); 
            g2.setComposite(AlphaComposite.SrcOver); 
        }

        // if rotation ... well
        if (rotateAngleNow != 0)
        {
            int sizeW = usedTexture.getHeight();
            int sizeH = usedTexture.getWidth();

            BufferedImage dimg = new BufferedImage(sizeW, sizeH, BufferedImage.TYPE_INT_ARGB);
            Graphics2D g = dimg.createGraphics();
            double sw = sizeW;
            double sh = sizeH;

            g.rotate(Math.toRadians(rotateAngleNow), sw/2, sh/2);

            // g.drawImage(orgImg, null, 0, 0);
            g.drawImage(usedTexture, null, 0, 0);
            usedTexture = dimg;
        }
        cache.put(currentKey, usedTexture);

        // updates info per tick
        return true;
    }

    public BufferedImage getCurrentRendering()
    {
        return cache.get(currentKey);
    }
        
    public void init(ParticleData c)
    {
        config = cloneConfig(c);
        init();
    }
    
    private void init()
    {
        currentKey = "org";
        orgTexture = ImageCache.getImageCache().getImage(config.mParticleImageName);
        if (orgTexture != null) // null should only be the case if emitter!
        {
            cache = cachePerId.get(config.mEmitterID);
            if (cache == null)
            {
                cache = new HashMap<String, BufferedImage>();
                cache.put(currentKey, orgTexture);
                cachePerId.put(""+config.mEmitterID, cache);
            }

            height = orgTexture.getHeight();
            width = orgTexture.getWidth();
        }

        if (config.mEmitPositionXRandom)
        {
            java.util.Random r = new java.util.Random();
            xD = r.nextInt(config.mEmitPositionX);
        }
        else
        {
            xD = config.mEmitPositionX; // position of the top/left corner of the particle
        }
        if (config.mEmitPositionYRandom)
        {
            java.util.Random r = new java.util.Random();
            yD = r.nextInt(config.mEmitPositionY);
        }
        else
        {
            yD = config.mEmitPositionY; // position of the top/left corner of the particle
        }

        // ticks are determined from emitter/engine
        // a tick is one call to "update", that can be
        // once in a second or 10 times in a second!

        lifeNow = config.mLife; // in ticks - respects tickCount!
        alphaFadeNow = 0;
        rotateAngleNow = 0;
        colorNow = config.mstartColor;
    }
    public static ParticleData cloneConfig(ParticleData c)
    {
        ParticleData nc = new ParticleData();

        nc.mClass = c.mClass;
        nc.mName = c.mName;
        
        nc.mEmitterName = c.mEmitterName;
        nc.mEmitterID = c.mEmitterID;
        nc.mGenerateEachTick = c.mGenerateEachTick;
        nc.mFade = c.mFade;
        nc.mRotate = c.mRotate;
        nc.mPositionX = c.mPositionX;
        nc.mPositionY = c.mPositionY;
        nc.mWidth = c.mWidth;
        nc.mHeight = c.mHeight;
        nc.mLife = c.mLife;
        nc.mLifeReduce = c.mLifeReduce;
        nc.mEmitPositionX = c.mEmitPositionX ;
        nc.mEmitPositionY = c.mEmitPositionY;
        nc.mEmitPositionXRandom = c.mEmitPositionXRandom;
        nc.mEmitPositionYRandom = c.mEmitPositionYRandom;
        nc.mUseTint = c.mUseTint;
        nc.mstartColor = c.mstartColor;
        nc.mendColor = c.mendColor;
        nc.mcolorAdditive = c.mcolorAdditive;
        nc.mParticleImageName = c.mParticleImageName;
        nc.mParticleEmitterName = c.mParticleEmitterName;
        nc.mStartVelocity1 = c.mStartVelocity1;
        nc.mStartVelocity2 = c.mStartVelocity2;
        nc.mStartAngle1 = c.mStartAngle1;
        nc.mStartAngle2 = c.mStartAngle2;
        nc.mAccelerationX = c.mAccelerationX;
        nc.mAccelerationY = c.mAccelerationY;
        nc.mtangentialAcceleration = c.mtangentialAcceleration;
        nc.mradialAcceleration = c.mradialAcceleration;        
        
        return nc;
    }


}
