package net.minecraft.client.render.entity;

import com.google.common.collect.Maps;
import java.util.Map;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.entity.feature.PandaHeldItemFeatureRenderer;
import net.minecraft.client.render.entity.model.EntityModelLayers;
import net.minecraft.client.render.entity.model.PandaEntityModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.passive.PandaEntity;
import net.minecraft.entity.passive.PandaEntity.Gene;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;

@Environment(EnvType.CLIENT)
public class PandaEntityRenderer extends MobEntityRenderer<PandaEntity, PandaEntityModel<PandaEntity>> {
	private static final Map<Gene, Identifier> TEXTURES = (Map<Gene, Identifier>)Util.make(Maps.newEnumMap(Gene.class), map -> {
		map.put(Gene.NORMAL, new Identifier("textures/entity/panda/panda.png"));
		map.put(Gene.LAZY, new Identifier("textures/entity/panda/lazy_panda.png"));
		map.put(Gene.WORRIED, new Identifier("textures/entity/panda/worried_panda.png"));
		map.put(Gene.PLAYFUL, new Identifier("textures/entity/panda/playful_panda.png"));
		map.put(Gene.BROWN, new Identifier("textures/entity/panda/brown_panda.png"));
		map.put(Gene.WEAK, new Identifier("textures/entity/panda/weak_panda.png"));
		map.put(Gene.AGGRESSIVE, new Identifier("textures/entity/panda/aggressive_panda.png"));
	});

	public PandaEntityRenderer(EntityRendererFactory.Context context) {
		super(context, new PandaEntityModel<>(context.getPart(EntityModelLayers.PANDA)), 0.9F);
		this.addFeature(new PandaHeldItemFeatureRenderer(this, context.getHeldItemRenderer()));
	}

	public Identifier getTexture(PandaEntity pandaEntity) {
		return (Identifier)TEXTURES.getOrDefault(pandaEntity.getProductGene(), (Identifier)TEXTURES.get(Gene.NORMAL));
	}

	protected void setupTransforms(PandaEntity pandaEntity, MatrixStack matrixStack, float f, float g, float h) {
		super.setupTransforms(pandaEntity, matrixStack, f, g, h);
		if (pandaEntity.playingTicks > 0) {
			int i = pandaEntity.playingTicks;
			int j = i + 1;
			float k = 7.0F;
			float l = pandaEntity.isBaby() ? 0.3F : 0.8F;
			if (i < 8) {
				float m = 90 * i / 7.0F;
				float n = 90 * j / 7.0F;
				float o = this.getAngle(m, n, j, h, 8.0F);
				matrixStack.translate(0.0F, (l + 0.2F) * (o / 90.0F), 0.0F);
				matrixStack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(-o));
			} else if (i < 16) {
				float m = (i - 8.0F) / 7.0F;
				float n = 90.0F + 90.0F * m;
				float p = 90.0F + 90.0F * (j - 8.0F) / 7.0F;
				float o = this.getAngle(n, p, j, h, 16.0F);
				matrixStack.translate(0.0F, l + 0.2F + (l - 0.2F) * (o - 90.0F) / 90.0F, 0.0F);
				matrixStack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(-o));
			} else if (i < 24.0F) {
				float m = (i - 16.0F) / 7.0F;
				float n = 180.0F + 90.0F * m;
				float p = 180.0F + 90.0F * (j - 16.0F) / 7.0F;
				float o = this.getAngle(n, p, j, h, 24.0F);
				matrixStack.translate(0.0F, l + l * (270.0F - o) / 90.0F, 0.0F);
				matrixStack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(-o));
			} else if (i < 32) {
				float m = (i - 24.0F) / 7.0F;
				float n = 270.0F + 90.0F * m;
				float p = 270.0F + 90.0F * (j - 24.0F) / 7.0F;
				float o = this.getAngle(n, p, j, h, 32.0F);
				matrixStack.translate(0.0F, l * ((360.0F - o) / 90.0F), 0.0F);
				matrixStack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(-o));
			}
		}

		float q = pandaEntity.getSittingAnimationProgress(h);
		if (q > 0.0F) {
			matrixStack.translate(0.0F, 0.8F * q, 0.0F);
			matrixStack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(MathHelper.lerp(q, pandaEntity.getPitch(), pandaEntity.getPitch() + 90.0F)));
			matrixStack.translate(0.0F, -1.0F * q, 0.0F);
			if (pandaEntity.isScaredByThunderstorm()) {
				float r = (float)(Math.cos(pandaEntity.age * 1.25) * Math.PI * 0.05F);
				matrixStack.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(r));
				if (pandaEntity.isBaby()) {
					matrixStack.translate(0.0F, 0.8F, 0.55F);
				}
			}
		}

		float r = pandaEntity.getLieOnBackAnimationProgress(h);
		if (r > 0.0F) {
			float k = pandaEntity.isBaby() ? 0.5F : 1.3F;
			matrixStack.translate(0.0F, k * r, 0.0F);
			matrixStack.multiply(RotationAxis.POSITIVE_X.rotationDegrees(MathHelper.lerp(r, pandaEntity.getPitch(), pandaEntity.getPitch() + 180.0F)));
		}
	}

	private float getAngle(float f, float g, int i, float h, float j) {
		return i < j ? MathHelper.lerp(h, f, g) : f;
	}
}
