package thebetweenlands.common.entity.mobs;

import java.util.List;

import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.EntityMoveHelper;
import net.minecraft.entity.ai.attributes.IAttribute;
import net.minecraft.entity.ai.attributes.RangedAttribute;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.network.play.server.SPacketSetPassengers;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EntityDamageSource;
import net.minecraft.util.EntityDamageSourceIndirect;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.NetworkRegistry.TargetPoint;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import thebetweenlands.api.entity.IEntityBL;
import thebetweenlands.client.render.particle.BLParticles;
import thebetweenlands.common.TheBetweenlands;
import thebetweenlands.common.entity.ai.EntityAIFlyRandomly;
import thebetweenlands.common.entity.ai.EntityAIMoveToDirect;
import thebetweenlands.common.entity.ai.EntityAITargetNonSneaking;
import thebetweenlands.common.entity.ai.EntityAIWightAttack;
import thebetweenlands.common.entity.ai.EntityAIWightBuffSwampHag;
import thebetweenlands.common.entity.movement.FlightMoveHelper;
import thebetweenlands.common.item.BLMaterialRegistry;
import thebetweenlands.common.network.clientbound.MessageWightVolatileParticles;
import thebetweenlands.common.registries.ItemRegistry;
import thebetweenlands.common.registries.LootTableRegistry;
import thebetweenlands.common.registries.SoundRegistry;

public class EntityWight extends EntityMob implements IEntityBL {

    public static final IAttribute VOLATILE_HEALTH_START_ATTRIB = (new RangedAttribute(null, "bl.volatileHealthStart", 1.0D, 0.0D, 1.0D)).setDescription("Volatile Health Percentage Start");
    public static final IAttribute VOLATILE_COOLDOWN_ATTRIB = (new RangedAttribute(null, "bl.volatileCooldown", 400.0D, 10.0D, Integer.MAX_VALUE)).setDescription("Volatile Cooldown");
    public static final IAttribute VOLATILE_FLIGHT_SPEED_ATTRIB = (new RangedAttribute(null, "bl.volatileFlightSpeed", 0.32D, 0.0D, 5.0D)).setDescription("Volatile Flight Speed");
    public static final IAttribute VOLATILE_LENGTH_ATTRIB = (new RangedAttribute(null, "bl.volatileLength", 600.0D, 0.0D, Integer.MAX_VALUE)).setDescription("Volatile Length");
    public static final IAttribute VOLATILE_MAX_DAMAGE_ATTRIB = (new RangedAttribute(null, "bl.volatileMaxDamage", 20.0D, 0.0D, Double.MAX_VALUE)).setDescription("Volatile Max Damage");

    protected static final DataParameter<Boolean> HIDING_STATE_DW = EntityDataManager.createKey(EntityWight.class, DataSerializers.BOOLEAN);
    protected static final DataParameter<Boolean> VOLATILE_STATE_DW = EntityDataManager.createKey(EntityWight.class, DataSerializers.BOOLEAN);
    protected final EntityMoveHelper flightMoveHelper;
    protected final EntityMoveHelper groundMoveHelper;
    private int hidingAnimationTicks = 0;
    private int lastHidingAnimationTicks = 0;
    private int volatileCooldownTicks = (int) VOLATILE_COOLDOWN_ATTRIB.getDefaultValue() / 2 + 20;
    private int volatileTicks = 0;
    private float volatileReceivedDamage = 0.0F;
    private boolean canTurnVolatile = true;
    private boolean canTurnVolatileOnTarget = false;
    private boolean didTurnVolatileOnPlayer = false;
    private static final DataParameter<Integer> GROW_TIMER = EntityDataManager.createKey(EntityWight.class, DataSerializers.VARINT);
    public int growCount, prevGrowCount;

    public EntityWight(World world) {
        super(world);
        this.experienceValue = 10;
        setSize(0.7F, 2.2F);
        this.setPathPriority(PathNodeType.WATER, 0.2F);
        this.flightMoveHelper = new FlightMoveHelper(this) {
            @Override
            protected double getFlightSpeed() {
                return this.entity.getAttributeMap().getAttributeInstance(VOLATILE_FLIGHT_SPEED_ATTRIB).getAttributeValue();
            }
        };
        this.moveHelper = this.groundMoveHelper = new EntityMoveHelper(this);
    }

    @Override
    protected void initEntityAI() {
        this.targetTasks.addTask(0, new EntityAITargetNonSneaking(this));
        this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true));

        this.tasks.addTask(0, new EntityAISwimming(this));
        this.tasks.addTask(1, new EntityAIWightAttack(this, 1.0D, false));
        this.tasks.addTask(2, new EntityAIWightBuffSwampHag(this));
        this.tasks.addTask(3, new EntityAIMoveToDirect<EntityWight>(this, this.getAttributeMap().getAttributeInstance(VOLATILE_FLIGHT_SPEED_ATTRIB).getAttributeValue()) {
            @Override
            protected Vec3d getTarget() {
                if (this.entity.volatileTicks >= 20) {
                    EntityLivingBase target = this.entity.getAttackTarget();
                    if (target != null) {
                        return new Vec3d(target.posX, target.posY + target.getEyeHeight() / 2.0D, target.posZ);
                    }
                }
                return null;
            }
        });
        this.tasks.addTask(4, new EntityAIMoveTowardsRestriction(this, 0.4D));
        this.tasks.addTask(5, new EntityAIWander(this, 0.3D));
        this.tasks.addTask(9, new EntityAIFlyRandomly<EntityWight>(this) {
            @Override
            public boolean shouldExecute() {
                return this.entity.isVolatile() && this.entity.volatileTicks >= 20 && this.entity.getAttackTarget() == null && super.shouldExecute();
            }

            @Override
            protected double getFlightSpeed() {
                return 0.1D;
            }
        });
        this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
        this.tasks.addTask(8, new EntityAILookIdle(this));
    }

    @Override
    protected void entityInit() {
        super.entityInit();
        this.dataManager.register(VOLATILE_STATE_DW, false);
        this.dataManager.register(HIDING_STATE_DW, false);
        dataManager.register(GROW_TIMER, 40);
    }

    @Override
    protected void applyEntityAttributes() {
        super.applyEntityAttributes();
        this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.33D);
        this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(76.0D);
        this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(6.0D);
        this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(80.0D);

        this.getAttributeMap().registerAttribute(VOLATILE_HEALTH_START_ATTRIB);
        this.getAttributeMap().registerAttribute(VOLATILE_COOLDOWN_ATTRIB);
        this.getAttributeMap().registerAttribute(VOLATILE_FLIGHT_SPEED_ATTRIB);
        this.getAttributeMap().registerAttribute(VOLATILE_LENGTH_ATTRIB);
        this.getAttributeMap().registerAttribute(VOLATILE_MAX_DAMAGE_ATTRIB);
    }

    @Override
	public void onUpdate() {
		if (this.world.isRemote) {
			prevGrowCount = growCount;
			growCount = getGrowTimer();
			if (getGrowTimer() > 0 && getGrowTimer() < 40)
				if (this.ticksExisted % 4 == 0)
					this.spawnVolatileParticles(true);
		}

        if (!this.world.isRemote) {
			if (isInTar()) {
				if (getGrowTimer() > 0)
					setGrowTimer(Math.max(0, getGrowTimer() - 1));
				if (getGrowTimer() <= 0) {
					EntityTarBeast tar_beast = new EntityTarBeast(getEntityWorld());
					tar_beast.setPositionAndRotation(posX, posY, posZ, rotationYaw, rotationPitch);
					tar_beast.setGrowTimer(0);
					getEntityWorld().spawnEntity(tar_beast);
					setDead();
				}
			}

			if (!isInTar() && getGrowTimer() < 40)
				setGrowTimer(Math.min(40, getGrowTimer() + 1));

            if (this.getAttackTarget() == null) {
                this.setHiding(true);

                this.canTurnVolatileOnTarget = false;
            } else {
                this.setHiding(false);

                if (this.canTurnVolatile && !this.isVolatile() && !this.isRiding() && this.canPossess(this.getAttackTarget()) && this.canTurnVolatileOnTarget) {
                    if (this.volatileCooldownTicks > 0) {
                        this.volatileCooldownTicks--;
                    }

                    if (this.getHealth() <= this.getMaxHealth() * this.getEntityAttribute(VOLATILE_HEALTH_START_ATTRIB).getAttributeValue() && this.volatileCooldownTicks <= 0) {
                        this.setVolatile(true);
                        this.didTurnVolatileOnPlayer = true;
                        this.volatileReceivedDamage = 0.0F;
                        this.volatileCooldownTicks = this.getMaxVolatileCooldown() + this.world.rand.nextInt(this.getMaxVolatileCooldown()) + 20;
                        this.volatileTicks = 0;

                        TheBetweenlands.networkWrapper.sendToAllAround(new MessageWightVolatileParticles(this), new TargetPoint(this.dimension, this.posX, this.posY, this.posZ, 32));
                        this.world.playSound(null, this.posX, this.posY, this.posZ, SoundRegistry.WIGHT_ATTACK, SoundCategory.HOSTILE, 1.6F, 1.0F);
                    }
                } else if (this.didTurnVolatileOnPlayer && this.isVolatile() && !this.canPossess(this.getAttackTarget())) {
                    this.setVolatile(false);
                    this.didTurnVolatileOnPlayer = false;
                }
            }
        }

        if (this.isVolatile()) {
        	if(!this.world.isRemote) {
	        	if (this.volatileTicks < this.getEntityAttribute(VOLATILE_LENGTH_ATTRIB).getAttributeValue()) {
	            	this.volatileTicks++;
	
	                if (this.volatileTicks >= 20) {
	                    this.noClip = true;
	                }
	            } else {
	                if (!this.world.isRemote) {
	                    this.motionY -= 0.075D;
	
	                    this.fallDistance = 0;
	
	                    if (this.didTurnVolatileOnPlayer && this.onGround) {
	                        this.setVolatile(false);
	                        this.didTurnVolatileOnPlayer = false;
	                    }
	                }
	
	                this.noClip = false;
	            }
	
	            if (this.volatileTicks < 20) {
	                this.moveHelper.setMoveTo(this.posX, this.posY + 1.0D, this.posZ, 0.15D);
	            }
	
	            if (this.getAttackTarget() != null) {
	                EntityLivingBase attackTarget = this.getAttackTarget();
	
	                if (this.getRidingEntity() == null && this.getDistance(attackTarget) < 1.75D && this.canPossess(attackTarget)) {
	                    this.startRiding(attackTarget, true);
	                    this.getServer().getPlayerList().sendPacketToAllPlayers(new SPacketSetPassengers(attackTarget));
	                }
	
	                if (this.getRidingEntity() == null) {
	                    double dx = attackTarget.posX - this.posX;
	                    double dz = attackTarget.posZ - this.posZ;
	                    double dy;
	                    if (attackTarget instanceof EntityLivingBase) {
	                        EntityLivingBase entitylivingbase = attackTarget;
	                        dy = entitylivingbase.posY + (double) entitylivingbase.getEyeHeight() - (this.posY + (double) this.getEyeHeight());
	                    } else {
	                        dy = (attackTarget.getEntityBoundingBox().minY + attackTarget.getEntityBoundingBox().maxY) / 2.0D - (this.posY + (double) this.getEyeHeight());
	                    }
	                    double dist = (double) MathHelper.sqrt(dx * dx + dz * dz);
	                    float yaw = (float) (Math.atan2(dz, dx) * 180.0D / Math.PI) - 90.0F;
	                    float pitch = (float) (-(Math.atan2(dy, dist) * 180.0D / Math.PI));
	                    this.setRotation(yaw, pitch);
	                    this.setRotationYawHead(yaw);
	                } else {
	                    this.setRotation(0, 0);
	                    this.setRotationYawHead(0);
	
	                    if (this.ticksExisted % 5 == 0 && this.canEntityBeSeen(this.getAttackTarget()) && !this.isWearingSkullMask(this.getAttackTarget())) {
	                        List<EntityVolatileSoul> existingSouls = this.world.getEntitiesWithinAABB(EntityVolatileSoul.class, this.getEntityBoundingBox().grow(16.0D, 16.0D, 16.0D));
	                        if (existingSouls.size() < 16) {
	                            EntityVolatileSoul soul = new EntityVolatileSoul(this.world);
	                            float mx = this.world.rand.nextFloat() - 0.5F;
	                            float my = this.world.rand.nextFloat() / 2.0F;
	                            float mz = this.world.rand.nextFloat() - 0.5F;
	                            Vec3d dir = new Vec3d(mx, my, mz).normalize();
	                            soul.setOwner(this.getUniqueID());
	                            soul.setLocationAndAngles(this.posX + dir.x * 0.5D, this.posY + dir.y * 1.5D, this.posZ + dir.z * 0.5D, 0, 0);
	                            soul.shoot(mx * 2.0D, my * 2.0D, mz * 2.0D, 1.0F, 1.0F);
	                            this.world.spawnEntity(soul);
	                        }
	                    }
	                }
	            }
	            
	            this.moveHelper = this.flightMoveHelper;
        	}

            if (this.world.isRemote && (this.getRidingEntity() == null || this.ticksExisted % 4 == 0)) {
                this.spawnVolatileParticles(false);
            }

            this.setSize(0.7F, 0.7F);
        } else {
        	if(!this.world.isRemote) {
	            this.noClip = false;
	            this.moveHelper = this.groundMoveHelper;
        	}
            
            this.setSize(0.7F, 2.2F);
        }

        this.lastHidingAnimationTicks = this.hidingAnimationTicks;
        if (this.isHiding()) {
            if (this.hidingAnimationTicks < 12)
                this.hidingAnimationTicks++;
        } else {
            if (this.hidingAnimationTicks > 0)
                this.hidingAnimationTicks--;
        }

        super.onUpdate();
    }

	public boolean isInTar() {
		return this.world.isMaterialInBB(this.getEntityBoundingBox().grow(-0.10000000149011612D, -0.4000000059604645D, -0.10000000149011612D), BLMaterialRegistry.TAR);
	}

	@Override
	protected boolean isMovementBlocked() {
		return super.isMovementBlocked() || isInTar() || getGrowTimer() < 40;
	}

	@Override
    public void fall(float distance, float damageMultiplier) {
        if (!this.isVolatile()) {
            super.fall(distance, damageMultiplier);
        }
    }

    @Override
    protected void updateFallState(double y, boolean onGroundIn, IBlockState state, BlockPos pos) {
        if (!this.isVolatile()) {
            super.updateFallState(y, onGroundIn, state, pos);
        }
    }

    @Override
    public void travel(float strafe, float up, float forward) {
        if (this.isVolatile()) {
            //Use flight movement

            if (this.isInWater()) {
                this.moveRelative(strafe, up, forward, 0.02F);
                this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ);
                this.motionX *= 0.800000011920929D;
                this.motionY *= 0.800000011920929D;
                this.motionZ *= 0.800000011920929D;
            } else if (this.isInLava()) {
                this.moveRelative(strafe,up, forward, 0.02F);
                this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ);
                this.motionX *= 0.5D;
                this.motionY *= 0.5D;
                this.motionZ *= 0.5D;
            } else {
                float f = 0.91F;

                if (this.onGround) {
                    f = this.world.getBlockState(new BlockPos(MathHelper.floor(this.posX), MathHelper.floor(this.getEntityBoundingBox().minY) - 1, MathHelper.floor(this.posZ))).getBlock().slipperiness * 0.91F;
                }

                float f1 = 0.16277136F / (f * f * f);
                this.moveRelative(strafe, up,  forward, this.onGround ? 0.1F * f1 : 0.02F);
                f = 0.91F;

                if (this.onGround) {
                    f = this.world.getBlockState(new BlockPos(MathHelper.floor(this.posX), MathHelper.floor(this.getEntityBoundingBox().minY) - 1, MathHelper.floor(this.posZ))).getBlock().slipperiness * 0.91F;
                }

                this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ);
                this.motionX *= (double) f;
                this.motionY *= (double) f;
                this.motionZ *= (double) f;
            }

            this.prevLimbSwingAmount = this.limbSwingAmount;
            double d1 = this.posX - this.prevPosX;
            double d0 = this.posZ - this.prevPosZ;
            float f2 = MathHelper.sqrt(d1 * d1 + d0 * d0) * 4.0F;

            if (f2 > 1.0F) {
                f2 = 1.0F;
            }

            this.limbSwingAmount += (f2 - this.limbSwingAmount) * 0.4F;
            this.limbSwing += this.limbSwingAmount;
        } else {
            //Use normal movement

            super.travel(strafe,up, forward);
        }
    }

    @Override
    public boolean isEntityInvulnerable(DamageSource source) {
        boolean isCreative = source instanceof EntityDamageSourceIndirect && ((EntityDamageSourceIndirect) source).getTrueSource() instanceof EntityPlayer && ((EntityPlayer) ((EntityDamageSourceIndirect) source).getTrueSource()).isCreative();
        return this.isHiding() && isCreative;
    }

    @Override
    public boolean canBePushed() {
        return !this.isHiding();
    }

    @Override
    protected ResourceLocation getLootTable() {
        return LootTableRegistry.WIGHT;
    }

    @Override
    public boolean attackEntityFrom(DamageSource source, float damage) {
        if (this.isVolatile() && source == DamageSource.IN_WALL) {
            return false;
        }
        float prevHealth = this.getHealth();
        boolean ret = super.attackEntityFrom(source, damage);
        float dealtDamage = prevHealth - this.getHealth();
        if (this.didTurnVolatileOnPlayer && this.isVolatile() && this.getRidingEntity() != null) {
            this.volatileReceivedDamage += dealtDamage;
            if (this.volatileReceivedDamage >= this.getEntityAttribute(VOLATILE_MAX_DAMAGE_ATTRIB).getAttributeValue()) {
                this.setVolatile(false);
                this.didTurnVolatileOnPlayer = false;
            }
        }
        if (this.getAttackTarget() != null && source instanceof EntityDamageSource && source.getTrueSource() == this.getAttackTarget()) {
            this.canTurnVolatileOnTarget = true;
        }
        return ret;
    }

    @Override
    public boolean attackEntityAsMob(Entity entity) {
        if (this.isVolatile()) {
            return false;
        }
        if (super.attackEntityAsMob(entity)) {
            if (entity == this.getAttackTarget()) {
                this.canTurnVolatileOnTarget = true;
            }
            return true;
        }
        return false;
    }

    @Override
    protected SoundEvent getAmbientSound() {
        return SoundRegistry.WIGHT_MOAN;
    }

    @Override
    protected SoundEvent getHurtSound(DamageSource damageSource) {
        return SoundRegistry.WIGHT_HURT;
    }

    @Override
    protected SoundEvent getDeathSound() {
        return SoundRegistry.WIGHT_DEATH;
    }

    @Override
    public void writeEntityToNBT(NBTTagCompound nbt) {
        super.writeEntityToNBT(nbt);
        nbt.setBoolean("volatileState", this.isVolatile());
        nbt.setInteger("volatileCooldown", this.volatileCooldownTicks);
        nbt.setInteger("volatileTicks", this.volatileTicks);
        nbt.setFloat("volatileReceivedDamage", this.volatileReceivedDamage);
        nbt.setBoolean("canTurnVolatileOnTarget", this.canTurnVolatileOnTarget);
        nbt.setBoolean("canTurnVolatile", this.canTurnVolatile);
        nbt.setBoolean("turnVolatileOnPlayer", this.didTurnVolatileOnPlayer);
        nbt.setInteger("grow_timer", getGrowTimer());
    }

    @Override
    public void readEntityFromNBT(NBTTagCompound nbt) {
        super.readEntityFromNBT(nbt);

        if (nbt.hasKey("volatileState")) {
            this.setVolatile(nbt.getBoolean("volatileState"));
        }
        if (nbt.hasKey("turnVolatileOnPlayer")) {
            this.didTurnVolatileOnPlayer = nbt.getBoolean("turnVolatileOnPlayer");
        }
        if (nbt.hasKey("volatileCooldown")) {
            this.volatileCooldownTicks = nbt.getInteger("volatileCooldown");
        }
        if (nbt.hasKey("volatileTicks")) {
            this.volatileTicks = nbt.getInteger("volatileTicks");
        }
        if (nbt.hasKey("volatileReceivedDamage")) {
            this.volatileReceivedDamage = nbt.getFloat("volatileReceivedDamage");
        }
        if (nbt.hasKey("canTurnVolatileOnTarget")) {
            this.canTurnVolatileOnTarget = nbt.getBoolean("canTurnVolatileOnTarget");
        }
        if (nbt.hasKey("canTurnVolatile")) {
            this.canTurnVolatile = nbt.getBoolean("canTurnVolatile");
        }

		if(nbt.hasKey("grow_timer"))
			setGrowTimer(nbt.getInteger("grow_timer")); 
    }

    @SideOnly(Side.CLIENT)
    private void spawnVolatileParticles(boolean tarred) {
        final double radius = 0.3F;

        final double cx = this.posX;
        final double cy = this.posY + 0.35D;
        final double cz = this.posZ;

        for (int i = 0; i < 8; i++) {
            double px = this.world.rand.nextFloat() * 0.7F;
            double py = this.world.rand.nextFloat() * 0.7F;
            double pz = this.world.rand.nextFloat() * 0.7F;
            Vec3d vec = new Vec3d(px, py, pz).subtract(new Vec3d(0.35F, 0.35F, 0.35F)).normalize();
            px = cx + vec.x * radius;
            py = cy + vec.y * radius;
            pz = cz + vec.z * radius;
			if (tarred) {
				float tintChange = 1F / 40F * growCount;
				BLParticles.STEAM_PURIFIER.spawn(this.world, px, py + 0.25D, pz).setRBGColorF(tintChange, tintChange,
						tintChange);
			} else
				BLParticles.STEAM_PURIFIER.spawn(this.world, px, py, pz);
		}
    }

    public boolean isHiding() {
        return this.getDataManager().get(HIDING_STATE_DW);
    }

    public void setHiding(boolean hiding) {
        this.getDataManager().set(HIDING_STATE_DW, hiding);
    }

	public int getGrowTimer() {
		return dataManager.get(GROW_TIMER);
	}

	public void setGrowTimer(int timer) {
		dataManager.set(GROW_TIMER, timer);
	}

    public float getHidingAnimation(float partialTicks) {
        return (this.lastHidingAnimationTicks + (this.hidingAnimationTicks - this.lastHidingAnimationTicks) * partialTicks) / 12.0F;
    }

	public float getGrowthFactor(float partialTicks) {
		return prevGrowCount + (growCount - prevGrowCount) * partialTicks;
	}

    public boolean isVolatile() {
        return this.getDataManager().get(VOLATILE_STATE_DW);
    }

    public void setVolatile(boolean isVolatile) {
        this.dataManager.set(VOLATILE_STATE_DW, isVolatile);

        if (!isVolatile) {
            Entity ridingEntity = this.getRidingEntity();
            if (ridingEntity != null) {
                this.dismountRidingEntity();
                if(!this.world.isRemote) {
                	this.getServer().getPlayerList().sendPacketToAllPlayers(new SPacketSetPassengers(ridingEntity));
                }
            }
        }
    }

    public int getMaxVolatileCooldown() {
        return (int) this.getEntityAttribute(VOLATILE_COOLDOWN_ATTRIB).getAttributeValue();
    }

    public boolean canPossess(EntityLivingBase entity) {
        if(entity instanceof EntitySwampHag) {
        	return true;
        }
        if(entity instanceof EntityPlayer) {
        	return !this.isWearingSkullMask(entity);
        }
        return false;
    }
    
    public boolean isWearingSkullMask(EntityLivingBase entity) {
    	if(entity instanceof EntityPlayer) {
        	ItemStack helmet = ((EntityPlayer)entity).getItemStackFromSlot(EntityEquipmentSlot.HEAD);
        	if(!helmet.isEmpty() && helmet.getItem() == ItemRegistry.SKULL_MASK) {
        		return true;
        	}
        }
    	return false;
    }

    public void setCanTurnVolatile(boolean canTurnVolatile) {
        this.canTurnVolatile = canTurnVolatile;
    }

    @Override
    public float getBlockPathWeight(BlockPos pos) {
        return 0.5F;
    }

    @Override
    protected boolean isValidLightLevel() {
    	return true;
    }
}
