package com.github.lunatrius.ingameinfo.tag;

import com.github.lunatrius.ingameinfo.reference.Reference;
import com.github.lunatrius.ingameinfo.tag.registry.TagRegistry;
import net.minecraft.entity.Entity;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.passive.EntityHorse;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

public abstract class TagRiding extends Tag {
    private static final int TICKS = 20;
    private static final double CONSTANT = 2.15858575199013618; // playerSpeed / internalPlayerSpeed (0.1)

    @Override
    public String getCategory() {
        return "riding";
    }

    public static class IsHorse extends TagRiding {
        @Override
        public String getValue() {
            return String.valueOf(player.getRidingEntity() instanceof EntityHorse);
        }
    }

    public static class HorseHealth extends TagRiding {
        @Override
        public String getValue() {
            final Entity ridingEntity = player.getRidingEntity();
            if (ridingEntity instanceof EntityHorse) {
                return String.valueOf(((EntityHorse) ridingEntity).getHealth());
            }
            return "-1";
        }
    }

    public static class HorseMaxHealth extends TagRiding {
        @Override
        public String getValue() {
            final Entity ridingEntity = player.getRidingEntity();
            if (ridingEntity instanceof EntityHorse) {
                return String.valueOf(((EntityHorse) ridingEntity).getMaxHealth());
            }
            return "-1";
        }
    }

    public static class HorseSpeed extends TagRiding {
        @Override
        public String getValue() {
            final Entity ridingEntity = player.getRidingEntity();
            if (ridingEntity instanceof EntityHorse) {
                return String.format(Locale.ENGLISH, "%.3f", TICKS * CONSTANT * ((EntityHorse) ridingEntity).getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).getAttributeValue());
            }
            return "-1";
        }
    }

    public static class HorseJump extends TagRiding {
        private final Map<Double, Double> jumpHeightCache = new HashMap<Double, Double>();

        private double getJumpHeight(final EntityHorse horse) {
            final double jumpStrength = horse.getHorseJumpStrength();

            final Double height = this.jumpHeightCache.get(jumpStrength);
            if (height != null) {
                return height;
            }

            double jumpHeight = 0;
            double velocity = jumpStrength;
            while (velocity > 0) {
                jumpHeight += velocity;
                velocity -= 0.08;
                velocity *= 0.98;
            }

            if (this.jumpHeightCache.size() > 16) {
                Reference.logger.trace("Clearing horse jump height cache.");
                this.jumpHeightCache.clear();
            }

            this.jumpHeightCache.put(jumpStrength, jumpHeight);
            return jumpHeight;
        }

        @Override
        public String getValue() {
            final Entity ridingEntity = player.getRidingEntity();
            if (ridingEntity instanceof EntityHorse) {
                return String.format(Locale.ENGLISH, "%.3f", getJumpHeight((EntityHorse) ridingEntity));
            }
            return "-1";
        }
    }

    public static void register() {
        TagRegistry.INSTANCE.register(new IsHorse().setName("ridinghorse"));
        TagRegistry.INSTANCE.register(new HorseHealth().setName("horsehealth"));
        TagRegistry.INSTANCE.register(new HorseMaxHealth().setName("horsemaxhealth"));
        TagRegistry.INSTANCE.register(new HorseSpeed().setName("horsespeed"));
        TagRegistry.INSTANCE.register(new HorseJump().setName("horsejumpstrength").setAliases("horsejumpstr"));
    }
}

@@ -289,22 +289,24 @@
 passive.
-Entity
+Abstract
 Horse;%0A%0A
@@ -825,30 +825,32 @@
  instanceof 
-Entity
+Abstract
 Horse);%0A    
@@ -1069,38 +1069,40 @@
 tity instanceof 
-Entity
+Abstract
 Horse) %7B%0A       
@@ -1126,38 +1126,40 @@
 tring.valueOf(((
-Entity
+Abstract
 Horse) ridingEnt
@@ -1443,38 +1443,40 @@
 tity instanceof 
-Entity
+Abstract
 Horse) %7B%0A       
@@ -1508,22 +1508,24 @@
 lueOf(((
-Entity
+Abstract
 Horse) r
@@ -1816,38 +1816,40 @@
 tity instanceof 
-Entity
+Abstract
 Horse) %7B%0A       
@@ -1923,22 +1923,24 @@
 ANT * ((
-Entity
+Abstract
 Horse) r
@@ -2278,22 +2278,24 @@
 t(final 
-Entity
+Abstract
 Horse ho
@@ -3218,22 +3218,24 @@
 tanceof 
-Entity
+Abstract
 Horse) %7B
@@ -3311,22 +3311,24 @@
 Height((
-Entity
+Abstract
 Horse) r

Fix horse related entities not being recognized properly. Fixes gh-49