package client.renderer.particle;

import client.Client;
import client.renderer.RenderBuffer;
import client.world.WorldClient;
import common.entity.Entity;
import common.init.SoundEvent;
import common.item.ItemDye;
import common.tags.TagObject;
import java.util.List;
import common.util.BoundingBox;
import common.util.ExtMath;
import common.world.World;

public class EntityFirework
{
    public static class Factory implements IParticleFactory
    {
        public EntityFX getEntityFX(int particleID, World worldIn, double xCoordIn, double yCoordIn, double zCoordIn, double xSpeedIn, double ySpeedIn, double zSpeedIn, int... p_178902_15_)
        {
            EntityFirework.SparkFX entityfirework$sparkfx = new EntityFirework.SparkFX(worldIn, xCoordIn, yCoordIn, zCoordIn, xSpeedIn, ySpeedIn, zSpeedIn, Client.CLIENT.effectRenderer);
            entityfirework$sparkfx.setAlphaF(0.99F);
            return entityfirework$sparkfx;
        }
    }

    public static class OverlayFX extends EntityFX
    {
        protected OverlayFX(World p_i46466_1_, double p_i46466_2_, double p_i46466_4_, double p_i46466_6_)
        {
            super(p_i46466_1_, p_i46466_2_, p_i46466_4_, p_i46466_6_);
            this.particleMaxAge = 4;
        }

        public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ)
        {
            float f = 0.25F;
            float f1 = 0.5F;
            float f2 = 0.125F;
            float f3 = 0.375F;
            float f4 = 7.1F * ExtMath.sin(((float)this.particleAge + partialTicks - 1.0F) * 0.25F * (float)Math.PI);
            this.particleAlpha = 0.6F - ((float)this.particleAge + partialTicks - 1.0F) * 0.25F * 0.5F;
            float f5 = (float)(this.prevX + (this.posX - this.prevX) * (double)partialTicks - interpPosX);
            float f6 = (float)(this.prevY + (this.posY - this.prevY) * (double)partialTicks - interpPosY);
            float f7 = (float)(this.prevZ + (this.posZ - this.prevZ) * (double)partialTicks - interpPosZ);
            int i = this.getBrightnessForRender(partialTicks);
            int j = i >> 16 & 65535;
            int k = i & 65535;
            worldRendererIn.pos((double)(f5 - rotationX * f4 - rotationXY * f4), (double)(f6 - rotationZ * f4), (double)(f7 - rotationYZ * f4 - rotationXZ * f4)).tex(0.5D, 0.375D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex();
            worldRendererIn.pos((double)(f5 - rotationX * f4 + rotationXY * f4), (double)(f6 + rotationZ * f4), (double)(f7 - rotationYZ * f4 + rotationXZ * f4)).tex(0.5D, 0.125D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex();
            worldRendererIn.pos((double)(f5 + rotationX * f4 + rotationXY * f4), (double)(f6 + rotationZ * f4), (double)(f7 + rotationYZ * f4 + rotationXZ * f4)).tex(0.25D, 0.125D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex();
            worldRendererIn.pos((double)(f5 + rotationX * f4 - rotationXY * f4), (double)(f6 - rotationZ * f4), (double)(f7 + rotationYZ * f4 - rotationXZ * f4)).tex(0.25D, 0.375D).color(this.particleRed, this.particleGreen, this.particleBlue, this.particleAlpha).lightmap(j, k).endVertex();
        }
    }

    public static class SparkFX extends EntityFX
    {
        private int baseTextureIndex = 160;
        private boolean trail;
        private boolean twinkle;
        private final EffectRenderer field_92047_az;
        private float fadeColourRed;
        private float fadeColourGreen;
        private float fadeColourBlue;
        private boolean hasFadeColour;

        public SparkFX(World p_i46465_1_, double p_i46465_2_, double p_i46465_4_, double p_i46465_6_, double p_i46465_8_, double p_i46465_10_, double p_i46465_12_, EffectRenderer p_i46465_14_)
        {
            super(p_i46465_1_, p_i46465_2_, p_i46465_4_, p_i46465_6_);
            this.motionX = p_i46465_8_;
            this.motionY = p_i46465_10_;
            this.motionZ = p_i46465_12_;
            this.field_92047_az = p_i46465_14_;
            this.particleScale *= 0.75F;
            this.particleMaxAge = 48 + this.rand.zrange(12);
            this.noClip = false;
        }

        public void setTrail(boolean trailIn)
        {
            this.trail = trailIn;
        }

        public void setTwinkle(boolean twinkleIn)
        {
            this.twinkle = twinkleIn;
        }

        public void setColour(int colour)
        {
            float f = (float)((colour & 16711680) >> 16) / 255.0F;
            float f1 = (float)((colour & 65280) >> 8) / 255.0F;
            float f2 = (float)((colour & 255) >> 0) / 255.0F;
            float f3 = 1.0F;
            this.setRBGColorF(f * f3, f1 * f3, f2 * f3);
        }

        public void setFadeColour(int faceColour)
        {
            this.fadeColourRed = (float)((faceColour & 16711680) >> 16) / 255.0F;
            this.fadeColourGreen = (float)((faceColour & 65280) >> 8) / 255.0F;
            this.fadeColourBlue = (float)((faceColour & 255) >> 0) / 255.0F;
            this.hasFadeColour = true;
        }

        public BoundingBox getCollisionBoundingBox()
        {
            return null;
        }

        public boolean canBePushed()
        {
            return false;
        }

        public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ)
        {
            if (!this.twinkle || this.particleAge < this.particleMaxAge / 3 || (this.particleAge + this.particleMaxAge) / 3 % 2 == 0)
            {
                super.renderParticle(worldRendererIn, entityIn, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ);
            }
        }

        public void onUpdate()
        {
            this.prevX = this.posX;
            this.prevY = this.posY;
            this.prevZ = this.posZ;

            if (this.particleAge++ >= this.particleMaxAge)
            {
                this.setDead();
            }

            if (this.particleAge > this.particleMaxAge / 2)
            {
                this.setAlphaF(1.0F - ((float)this.particleAge - (float)(this.particleMaxAge / 2)) / (float)this.particleMaxAge);

                if (this.hasFadeColour)
                {
                    this.particleRed += (this.fadeColourRed - this.particleRed) * 0.2F;
                    this.particleGreen += (this.fadeColourGreen - this.particleGreen) * 0.2F;
                    this.particleBlue += (this.fadeColourBlue - this.particleBlue) * 0.2F;
                }
            }

            this.setParticleTextureIndex(this.baseTextureIndex + (7 - this.particleAge * 8 / this.particleMaxAge));
            this.motionY -= 0.004D;
            this.moveEntity(this.motionX, this.motionY, this.motionZ);
            this.motionX *= 0.9100000262260437D;
            this.motionY *= 0.9100000262260437D;
            this.motionZ *= 0.9100000262260437D;

            if (this.onGround)
            {
                this.motionX *= 0.699999988079071D;
                this.motionZ *= 0.699999988079071D;
            }

            if (this.trail && this.particleAge < this.particleMaxAge / 2 && (this.particleAge + this.particleMaxAge) % 2 == 0)
            {
                EntityFirework.SparkFX entityfirework$sparkfx = new EntityFirework.SparkFX(this.worldObj, this.posX, this.posY, this.posZ, 0.0D, 0.0D, 0.0D, this.field_92047_az);
                entityfirework$sparkfx.setAlphaF(0.99F);
                entityfirework$sparkfx.setRBGColorF(this.particleRed, this.particleGreen, this.particleBlue);
                entityfirework$sparkfx.particleAge = entityfirework$sparkfx.particleMaxAge / 2;

                if (this.hasFadeColour)
                {
                    entityfirework$sparkfx.hasFadeColour = true;
                    entityfirework$sparkfx.fadeColourRed = this.fadeColourRed;
                    entityfirework$sparkfx.fadeColourGreen = this.fadeColourGreen;
                    entityfirework$sparkfx.fadeColourBlue = this.fadeColourBlue;
                }

                entityfirework$sparkfx.twinkle = this.twinkle;
                this.field_92047_az.addEffect(entityfirework$sparkfx);
            }
        }

        public int getBrightnessForRender(float partialTicks)
        {
            return 15728880;
        }

        public float getBrightness(float partialTicks)
        {
            return 1.0F;
        }
    }

    public static class StarterFX extends EntityFX
    {
        private int fireworkAge;
        private final EffectRenderer theEffectRenderer;
        private List<TagObject> fireworkExplosions;
        boolean twinkle;

        public StarterFX(World p_i46464_1_, double p_i46464_2_, double p_i46464_4_, double p_i46464_6_, double p_i46464_8_, double p_i46464_10_, double p_i46464_12_, EffectRenderer p_i46464_14_, TagObject p_i46464_15_)
        {
            super(p_i46464_1_, p_i46464_2_, p_i46464_4_, p_i46464_6_, 0.0D, 0.0D, 0.0D);
            this.motionX = p_i46464_8_;
            this.motionY = p_i46464_10_;
            this.motionZ = p_i46464_12_;
            this.theEffectRenderer = p_i46464_14_;
            this.particleMaxAge = 8;

            if (p_i46464_15_ != null)
            {
                this.fireworkExplosions = p_i46464_15_.getList("Explosions");

                if (this.fireworkExplosions.size() == 0)
                {
                    this.fireworkExplosions = null;
                }
                else
                {
                    this.particleMaxAge = this.fireworkExplosions.size() * 2 - 1;

                    for (int i = 0; i < this.fireworkExplosions.size(); ++i)
                    {
                        TagObject tag = this.fireworkExplosions.get(i);

                        if (tag.getBool("Flicker"))
                        {
                            this.twinkle = true;
                            this.particleMaxAge += 15;
                            break;
                        }
                    }
                }
            }
        }

        public void renderParticle(RenderBuffer worldRendererIn, Entity entityIn, float partialTicks, float rotationX, float rotationZ, float rotationYZ, float rotationXY, float rotationXZ)
        {
        }

        public void onUpdate()
        {
            if (this.fireworkAge == 0 && this.fireworkExplosions != null)
            {
                boolean flag = this.isFarAway();
                boolean flag1 = false;

                if (this.fireworkExplosions.size() >= 3)
                {
                    flag1 = true;
                }
                else
                {
                    for (int i = 0; i < this.fireworkExplosions.size(); ++i)
                    {
                        TagObject tag = this.fireworkExplosions.get(i);

                        if (tag.getByte("Type") == 1)
                        {
                            flag1 = true;
                            break;
                        }
                    }
                }

                SoundEvent s1 = flag1 ? (flag ? SoundEvent.BLAST_LARGE_FAR : SoundEvent.BLAST_LARGE) : 
                	(flag ? SoundEvent.BLAST_SMALL_FAR : SoundEvent.BLAST_SMALL);
                ((WorldClient)this.worldObj).playSound(this.posX, this.posY, this.posZ, s1, 20.0F);
            }

            if (this.fireworkAge % 2 == 0 && this.fireworkExplosions != null && this.fireworkAge / 2 < this.fireworkExplosions.size())
            {
                int k = this.fireworkAge / 2;
                TagObject tag = this.fireworkExplosions.get(k);
                int l = tag.getByte("Type");
                boolean flag4 = tag.getBool("Trail");
                boolean flag2 = tag.getBool("Flicker");
                int[] aint = tag.getIntArray("Colors");
                int[] aint1 = tag.getIntArray("FadeColors");

                if (aint.length == 0)
                {
                    aint = new int[] {ItemDye.dyeColors[0]};
                }

                if (l == 1)
                {
                    this.createBall(0.5D, 4, aint, aint1, flag4, flag2);
                }
                else if (l == 2)
                {
                    this.createShaped(0.5D, new double[][] {
                    	{0.0D, 1.0D}, {0.3455D, 0.309D}, {0.9511D, 0.309D}, {0.3795918367346939D, -0.12653061224489795D}, 
                    	{0.6122448979591837D, -0.8040816326530612D}, {0.0D, -0.35918367346938773D}
                    }, aint, aint1, flag4, flag2, false, 4);
                }
                else if (l == 3)
                {
                    this.createShaped(0.5D, new double[][] {
                    	{0.187 - 0.5, 1.0 - 0.016}, {1.0 - 0.5, 1.0 - 0.625}, {0.0 - 0.5, 1.0 - 0.625}, 
                    	{0.812 - 0.5, 1.0 - 0.016}, {0.5 - 0.5, 1.0 - 1.0}, {0.187 - 0.5, 1.0 - 0.016}
                    }, aint, aint1, flag4, flag2, true, 8);
                }
                else if (l == 4)
                {
                    this.createBurst(aint, aint1, flag4, flag2);
                }
                else
                {
                    this.createBall(0.25D, 2, aint, aint1, flag4, flag2);
                }

                int j = aint[0];
                float f = (float)((j & 16711680) >> 16) / 255.0F;
                float f1 = (float)((j & 65280) >> 8) / 255.0F;
                float f2 = (float)((j & 255) >> 0) / 255.0F;
                EntityFirework.OverlayFX entityfirework$overlayfx = new EntityFirework.OverlayFX(this.worldObj, this.posX, this.posY, this.posZ);
                entityfirework$overlayfx.setRBGColorF(f, f1, f2);
                this.theEffectRenderer.addEffect(entityfirework$overlayfx);
            }

            ++this.fireworkAge;

            if (this.fireworkAge > this.particleMaxAge)
            {
                if (this.twinkle)
                {
                    boolean flag3 = this.isFarAway();
                    SoundEvent s = flag3 ? SoundEvent.TWINKLE_FAR : SoundEvent.TWINKLE;
                    ((WorldClient)this.worldObj).playSound(this.posX, this.posY, this.posZ, s, 20.0F);
                }

                this.setDead();
            }
        }

        private boolean isFarAway()
        {
            Client gm = Client.CLIENT;
            return gm == null || gm.getRenderViewEntity() == null || gm.getRenderViewEntity().getDistanceSq(this.posX, this.posY, this.posZ) >= 256.0D;
        }

        private void createParticle(double p_92034_1_, double p_92034_3_, double p_92034_5_, double p_92034_7_, double p_92034_9_, double p_92034_11_, int[] p_92034_13_, int[] p_92034_14_, boolean p_92034_15_, boolean p_92034_16_)
        {
            EntityFirework.SparkFX entityfirework$sparkfx = new EntityFirework.SparkFX(this.worldObj, p_92034_1_, p_92034_3_, p_92034_5_, p_92034_7_, p_92034_9_, p_92034_11_, this.theEffectRenderer);
            entityfirework$sparkfx.setAlphaF(0.99F);
            entityfirework$sparkfx.setTrail(p_92034_15_);
            entityfirework$sparkfx.setTwinkle(p_92034_16_);
            int i = this.rand.zrange(p_92034_13_.length);
            entityfirework$sparkfx.setColour(p_92034_13_[i]);

            if (p_92034_14_ != null && p_92034_14_.length > 0)
            {
                entityfirework$sparkfx.setFadeColour(p_92034_14_[this.rand.zrange(p_92034_14_.length)]);
            }

            this.theEffectRenderer.addEffect(entityfirework$sparkfx);
        }

        private void createBall(double speed, int size, int[] colours, int[] fadeColours, boolean trail, boolean twinkleIn)
        {
            double d0 = this.posX;
            double d1 = this.posY;
            double d2 = this.posZ;

            for (int i = -size; i <= size; ++i)
            {
                for (int j = -size; j <= size; ++j)
                {
                    for (int k = -size; k <= size; ++k)
                    {
                        double d3 = (double)j + (this.rand.doublev() - this.rand.doublev()) * 0.5D;
                        double d4 = (double)i + (this.rand.doublev() - this.rand.doublev()) * 0.5D;
                        double d5 = (double)k + (this.rand.doublev() - this.rand.doublev()) * 0.5D;
                        double d6 = (double)ExtMath.sqrtd(d3 * d3 + d4 * d4 + d5 * d5) / speed + this.rand.gaussian() * 0.05D;
                        this.createParticle(d0, d1, d2, d3 / d6, d4 / d6, d5 / d6, colours, fadeColours, trail, twinkleIn);

                        if (i != -size && i != size && j != -size && j != size)
                        {
                            k += size * 2 - 1;
                        }
                    }
                }
            }
        }

        private void createShaped(double speed, double[][] shape, int[] colours, int[] fadeColours, boolean trail, boolean twinkleIn, 
        		boolean p_92038_8_, int div)
        {
            double d0 = shape[0][0];
            double d1 = shape[0][1];
            this.createParticle(this.posX, this.posY, this.posZ, d0 * speed, d1 * speed, 0.0D, colours, fadeColours, trail, twinkleIn);
            float f = this.rand.floatv() * (float)Math.PI;
            double d2 = p_92038_8_ ? 0.034D : 0.34D;
            double shift = 1.0 / (double)div;

            for (int i = 0; i < 3; ++i)
            {
                double d3 = (double)f + (double)((float)i * (float)Math.PI) * d2;
                double d4 = d0;
                double d5 = d1;

                for (int j = 1; j < shape.length; ++j)
                {
                    double d6 = shape[j][0];
                    double d7 = shape[j][1];

                    for (double d8 = shift; d8 <= 1.0D; d8 += shift)
                    {
                        double d9 = (d4 + (d6 - d4) * d8) * speed;
                        double d10 = (d5 + (d7 - d5) * d8) * speed;
                        double d11 = d9 * Math.sin(d3);
                        d9 = d9 * Math.cos(d3);

                        for (double d12 = -1.0D; d12 <= 1.0D; d12 += 2.0D)
                        {
                            this.createParticle(this.posX, this.posY, this.posZ, d9 * d12, d10, d11 * d12, colours, fadeColours, trail, twinkleIn);
                        }
                    }

                    d4 = d6;
                    d5 = d7;
                }
            }
        }

        private void createBurst(int[] colours, int[] fadeColours, boolean trail, boolean twinkleIn)
        {
            double d0 = this.rand.gaussian() * 0.05D;
            double d1 = this.rand.gaussian() * 0.05D;

            for (int i = 0; i < 70; ++i)
            {
                double d2 = this.motionX * 0.5D + this.rand.gaussian() * 0.15D + d0;
                double d3 = this.motionZ * 0.5D + this.rand.gaussian() * 0.15D + d1;
                double d4 = this.motionY * 0.5D + this.rand.doublev() * 0.5D;
                this.createParticle(this.posX, this.posY, this.posZ, d2, d4, d3, colours, fadeColours, trail, twinkleIn);
            }
        }

        public int getFXLayer()
        {
            return 0;
        }
    }
}
