package com.minelittlepony.client.render.blockentity.skull;

import com.google.common.base.Suppliers;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.client.model.AbstractPonyModel;
import com.minelittlepony.client.render.MobRenderers;
import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer.ISkull;
import com.minelittlepony.client.render.entity.state.PonyRenderState;
import com.minelittlepony.mson.api.ModelKey;

import java.util.function.Supplier;

import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.component.type.ProfileComponent;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.RotationAxis;

import org.jetbrains.annotations.Nullable;
import org.joml.Vector3f;

public class MobSkull<S extends PonyRenderState> implements ISkull {
    private final Identifier texture;
    private final MobRenderers type;

    private final Supplier<AbstractPonyModel<?>> ponyHead;
    private final Supplier<S> state;

    MobSkull(Identifier texture, MobRenderers type, ModelKey<? extends AbstractPonyModel<?>> modelKey, Supplier<S> state) {
        this.texture = texture;
        this.type = type;
        this.state = Suppliers.memoize(state::get);
        this.ponyHead = Suppliers.memoize(modelKey::createModel);
    }

    @Override
    public boolean canRender(PonyConfig config) {
        return config.ponyskulls.get() && type.option().get();
    }

    @Override
    public Identifier getSkinResource(@Nullable ProfileComponent profile) {
        return texture;
    }

    @Override
    public boolean bindPony(Pony pony) {
        S state = this.state.get();
        state.pony = pony;
        state.race = pony.race();
        state.attributes.size = pony.size();
        state.attributes.metadata = pony.metadata();
        return true;
    }

    @Override
    public void setAngles(float yaw, float animationProgress) {
        Vector3f v = new Vector3f(0, -2, 1.99F);
        v.rotate(RotationAxis.POSITIVE_Y.rotationDegrees(yaw));
        ponyHead.get().setVisible(true);
        ponyHead.get().setAngles(state.get());
        ModelPart head = ponyHead.get().getHead();
        head.pivotX = v.x;
        head.pivotY = v.y;
        head.pivotZ = v.z;
        ponyHead.get().setHeadRotation(animationProgress, yaw, 0);
    }

    @Override
    public void render(MatrixStack stack, VertexConsumer vertices, int light, int overlay, int color) {
        ponyHead.get().headRenderList.accept(stack, vertices, light, overlay, color);
    }
}
