package xyz.illuc.neuralgiacore.peripherals;

import com.simibubi.create.content.contraptions.bearing.MechanicalBearingBlockEntity;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.api.peripheral.IPeripheral;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

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

public class BearingPeripheral implements IPeripheral {

    private final MechanicalBearingBlockEntity bearing;

    public BearingPeripheral(MechanicalBearingBlockEntity bearing) {
        this.bearing = bearing;
    }

    @NotNull
    @Override
    public String getType() {
        return "mechanical_bearing";
    }

    @Override
    public boolean equals(@Nullable IPeripheral other) {
        return this == other;
    }

    @LuaFunction
    public final void setAngle(double angle) throws LuaException {
        if (!bearing.isRunning()) {
            throw new LuaException("Bearing must be running (assembled) to set angle");
        }

        if (angle < 0 || angle > 360) {
            throw new LuaException("Angle must be between 0 and 360 degrees");
        }

        bearing.setAngle((float) angle);
        bearing.setChanged();
    }

    @LuaFunction
    public final double getAngle() {
        return bearing.getInterpolatedAngle(0f);
    }

    @LuaFunction
    public final double getAngularSpeed() {
        return bearing.getAngularSpeed();
    }

    @LuaFunction
    public final boolean isRunning() {
        return bearing.isRunning();
    }

    @LuaFunction
    public final boolean isNearInitialAngle() {
        return bearing.isNearInitialAngle();
    }

    @LuaFunction
    public final double getSpeed() {
        return bearing.getSpeed();
    }

    @LuaFunction
    public final Map<String, Object> getInfo() {
        Map<String, Object> info = new HashMap<>();
        info.put("angle", bearing.getInterpolatedAngle(0f));
        info.put("angularSpeed", bearing.getAngularSpeed());
        info.put("running", bearing.isRunning());
        info.put("speed", bearing.getSpeed());
        info.put("nearInitialAngle", bearing.isNearInitialAngle());

        if (bearing.getMovedContraption() != null) {
            info.put("stalled", bearing.getMovedContraption().isStalled());
        }

        return info;
    }

    @LuaFunction
    public final void rotate(double degrees) throws LuaException {
        if (!bearing.isRunning()) {
            throw new LuaException("Bearing must be running (assembled) to rotate");
        }

        double currentAngle = bearing.getInterpolatedAngle(0f);
        double newAngle = (currentAngle + degrees) % 360;
        if (newAngle < 0) {
            newAngle += 360;
        }

        bearing.setAngle((float) newAngle);
        bearing.setChanged();
    }

}