/*
 * Decompiled with CFR 0.152.
 * 
 * Could not load the following classes:
 *  meteordevelopment.orbit.EventHandler
 *  net.minecraft.class_1297
 *  net.minecraft.class_1657
 *  net.minecraft.class_1676
 *  net.minecraft.class_1685
 *  net.minecraft.class_1687
 *  net.minecraft.class_1764
 *  net.minecraft.class_1771
 *  net.minecraft.class_1776
 *  net.minecraft.class_1779
 *  net.minecraft.class_1787
 *  net.minecraft.class_1792
 *  net.minecraft.class_1799
 *  net.minecraft.class_1811
 *  net.minecraft.class_1823
 *  net.minecraft.class_1835
 *  net.minecraft.class_1887
 *  net.minecraft.class_1893
 *  net.minecraft.class_2350
 *  net.minecraft.class_238
 *  net.minecraft.class_239
 *  net.minecraft.class_239$class_240
 *  net.minecraft.class_3532
 *  net.minecraft.class_3965
 *  net.minecraft.class_3966
 *  net.minecraft.class_4537
 *  net.minecraft.class_5321
 *  net.minecraft.class_7923
 *  net.minecraft.class_9239
 *  org.joml.Vector3d
 *  org.joml.Vector3dc
 */
package meteordevelopment.meteorclient.systems.modules.render;

import java.util.ArrayList;
import java.util.List;
import meteordevelopment.meteorclient.events.render.Render3DEvent;
import meteordevelopment.meteorclient.renderer.ShapeMode;
import meteordevelopment.meteorclient.settings.BoolSetting;
import meteordevelopment.meteorclient.settings.ColorSetting;
import meteordevelopment.meteorclient.settings.DoubleSetting;
import meteordevelopment.meteorclient.settings.EnumSetting;
import meteordevelopment.meteorclient.settings.IntSetting;
import meteordevelopment.meteorclient.settings.ItemListSetting;
import meteordevelopment.meteorclient.settings.Setting;
import meteordevelopment.meteorclient.settings.SettingGroup;
import meteordevelopment.meteorclient.systems.modules.Categories;
import meteordevelopment.meteorclient.systems.modules.Module;
import meteordevelopment.meteorclient.utils.Utils;
import meteordevelopment.meteorclient.utils.entity.simulator.ProjectileEntitySimulator;
import meteordevelopment.meteorclient.utils.entity.simulator.SimulationStep;
import meteordevelopment.meteorclient.utils.misc.Pool;
import meteordevelopment.meteorclient.utils.render.color.SettingColor;
import meteordevelopment.orbit.EventHandler;
import net.minecraft.class_1297;
import net.minecraft.class_1657;
import net.minecraft.class_1676;
import net.minecraft.class_1685;
import net.minecraft.class_1687;
import net.minecraft.class_1764;
import net.minecraft.class_1771;
import net.minecraft.class_1776;
import net.minecraft.class_1779;
import net.minecraft.class_1787;
import net.minecraft.class_1792;
import net.minecraft.class_1799;
import net.minecraft.class_1811;
import net.minecraft.class_1823;
import net.minecraft.class_1835;
import net.minecraft.class_1887;
import net.minecraft.class_1893;
import net.minecraft.class_2350;
import net.minecraft.class_238;
import net.minecraft.class_239;
import net.minecraft.class_3532;
import net.minecraft.class_3965;
import net.minecraft.class_3966;
import net.minecraft.class_4537;
import net.minecraft.class_5321;
import net.minecraft.class_7923;
import net.minecraft.class_9239;
import org.joml.Vector3d;
import org.joml.Vector3dc;

public class Trajectories
extends Module {
    private final SettingGroup sgGeneral;
    private final SettingGroup sgRender;
    private final Setting<List<class_1792>> items;
    private final Setting<Boolean> otherPlayers;
    private final Setting<Boolean> firedProjectiles;
    private final Setting<Boolean> ignoreWitherSkulls;
    private final Setting<Boolean> accurate;
    public final Setting<Integer> simulationSteps;
    private final Setting<Integer> ignoreFirstTicks;
    private final Setting<ShapeMode> shapeMode;
    private final Setting<SettingColor> sideColor;
    private final Setting<SettingColor> lineColor;
    private final Setting<Boolean> renderPositionBox;
    private final Setting<Double> positionBoxSize;
    private final Setting<SettingColor> positionSideColor;
    private final Setting<SettingColor> positionLineColor;
    private final ProjectileEntitySimulator simulator;
    private final Pool<Vector3d> vec3s;
    private final List<Path> paths;
    private static final double MULTISHOT_OFFSET = Math.toRadians(10.0);

    public Trajectories() {
        super(Categories.Render, "trajectories", "Predicts the trajectory of throwable items.");
        this.sgGeneral = this.settings.getDefaultGroup();
        this.sgRender = this.settings.createGroup("Render");
        this.items = this.sgGeneral.add(((ItemListSetting.Builder)((ItemListSetting.Builder)((ItemListSetting.Builder)new ItemListSetting.Builder().name("items")).description("Items to display trajectories for.")).defaultValue(this.getDefaultItems())).filter(this::itemFilter).build());
        this.otherPlayers = this.sgGeneral.add(((BoolSetting.Builder)((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("other-players")).description("Calculates trajectories for other players.")).defaultValue(true)).build());
        this.firedProjectiles = this.sgGeneral.add(((BoolSetting.Builder)((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("fired-projectiles")).description("Calculates trajectories for already fired projectiles.")).defaultValue(false)).build());
        this.ignoreWitherSkulls = this.sgGeneral.add(((BoolSetting.Builder)((BoolSetting.Builder)((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("ignore-wither-skulls")).description("Whether to ignore fired wither skulls.")).defaultValue(false)).visible(this.firedProjectiles::get)).build());
        this.accurate = this.sgGeneral.add(((BoolSetting.Builder)((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("accurate")).description("Whether or not to calculate more accurate.")).defaultValue(false)).build());
        this.simulationSteps = this.sgGeneral.add(((IntSetting.Builder)((IntSetting.Builder)((IntSetting.Builder)new IntSetting.Builder().name("simulation-steps")).description("How many steps to simulate projectiles. Zero for no limit")).defaultValue(500)).sliderMax(5000).build());
        this.ignoreFirstTicks = this.sgRender.add(((IntSetting.Builder)((IntSetting.Builder)((IntSetting.Builder)new IntSetting.Builder().name("ignore-rendering-first-ticks")).description("Ignores rendering the first given ticks, to make the rest of the path more visible.")).defaultValue(3)).min(0).build());
        this.shapeMode = this.sgRender.add(((EnumSetting.Builder)((EnumSetting.Builder)((EnumSetting.Builder)new EnumSetting.Builder().name("shape-mode")).description("How the shapes are rendered.")).defaultValue(ShapeMode.Both)).build());
        this.sideColor = this.sgRender.add(((ColorSetting.Builder)((ColorSetting.Builder)new ColorSetting.Builder().name("side-color")).description("The side color.")).defaultValue(new SettingColor(255, 150, 0, 35)).build());
        this.lineColor = this.sgRender.add(((ColorSetting.Builder)((ColorSetting.Builder)new ColorSetting.Builder().name("line-color")).description("The line color.")).defaultValue(new SettingColor(255, 150, 0)).build());
        this.renderPositionBox = this.sgRender.add(((BoolSetting.Builder)((BoolSetting.Builder)((BoolSetting.Builder)new BoolSetting.Builder().name("render-position-boxes")).description("Renders the actual position the projectile will be at each tick along it's trajectory.")).defaultValue(false)).build());
        this.positionBoxSize = this.sgRender.add(((DoubleSetting.Builder)((DoubleSetting.Builder)((DoubleSetting.Builder)new DoubleSetting.Builder().name("position-box-size")).description("The size of the box drawn at the simulated positions.")).defaultValue(0.02).sliderRange(0.01, 0.1).visible(this.renderPositionBox::get)).build());
        this.positionSideColor = this.sgRender.add(((ColorSetting.Builder)((ColorSetting.Builder)((ColorSetting.Builder)new ColorSetting.Builder().name("position-side-color")).description("The side color.")).defaultValue(new SettingColor(255, 150, 0, 35)).visible(this.renderPositionBox::get)).build());
        this.positionLineColor = this.sgRender.add(((ColorSetting.Builder)((ColorSetting.Builder)((ColorSetting.Builder)new ColorSetting.Builder().name("position-line-color")).description("The line color.")).defaultValue(new SettingColor(255, 150, 0)).visible(this.renderPositionBox::get)).build());
        this.simulator = new ProjectileEntitySimulator();
        this.vec3s = new Pool<Vector3d>(Vector3d::new);
        this.paths = new ArrayList<Path>();
    }

    private boolean itemFilter(class_1792 item) {
        return item instanceof class_1811 || item instanceof class_1787 || item instanceof class_1835 || item instanceof class_1823 || item instanceof class_1771 || item instanceof class_1776 || item instanceof class_1779 || item instanceof class_4537 || item instanceof class_9239;
    }

    private List<class_1792> getDefaultItems() {
        ArrayList<class_1792> items = new ArrayList<class_1792>();
        for (class_1792 item : class_7923.field_41178) {
            if (!this.itemFilter(item)) continue;
            items.add(item);
        }
        return items;
    }

    private Path getEmptyPath() {
        for (Path path : this.paths) {
            if (!path.points.isEmpty()) continue;
            return path;
        }
        Path path = new Path();
        this.paths.add(path);
        return path;
    }

    private void calculatePath(class_1657 player, float tickDelta) {
        for (Path path : this.paths) {
            path.clear();
        }
        class_1799 itemStack = player.method_6047();
        if (!this.items.get().contains(itemStack.method_7909())) {
            itemStack = player.method_6079();
            if (!this.items.get().contains(itemStack.method_7909())) {
                return;
            }
        }
        if (!this.simulator.set((class_1297)player, itemStack, 0.0, this.accurate.get(), tickDelta)) {
            return;
        }
        Path p = this.getEmptyPath().calculate();
        if (player == this.mc.field_1724) {
            p.ignoreFirstTicks();
        }
        if (itemStack.method_7909() instanceof class_1764 && Utils.hasEnchantment(itemStack, (class_5321<class_1887>)class_1893.field_9108)) {
            if (!this.simulator.set((class_1297)player, itemStack, MULTISHOT_OFFSET, this.accurate.get(), tickDelta)) {
                return;
            }
            p = this.getEmptyPath().calculate();
            if (player == this.mc.field_1724) {
                p.ignoreFirstTicks();
            }
            if (!this.simulator.set((class_1297)player, itemStack, -MULTISHOT_OFFSET, this.accurate.get(), tickDelta)) {
                return;
            }
            p = this.getEmptyPath().calculate();
            if (player == this.mc.field_1724) {
                p.ignoreFirstTicks();
            }
        }
    }

    private void calculateFiredPath(class_1297 entity, double tickDelta) {
        for (Path path : this.paths) {
            path.clear();
        }
        if (!this.simulator.set(entity)) {
            return;
        }
        this.getEmptyPath().setStart(entity, tickDelta).calculate();
    }

    @EventHandler
    private void onRender(Render3DEvent event) {
        float tickDelta = this.mc.field_1687.method_54719().method_54754() ? 1.0f : event.tickDelta;
        for (class_1657 player : this.mc.field_1687.method_18456()) {
            if (!this.otherPlayers.get().booleanValue() && player != this.mc.field_1724) continue;
            this.calculatePath(player, tickDelta);
            for (Path path : this.paths) {
                path.render(event);
            }
        }
        if (this.firedProjectiles.get().booleanValue()) {
            for (class_1297 entity : this.mc.field_1687.method_18112()) {
                if (!(entity instanceof class_1676) || this.ignoreWitherSkulls.get().booleanValue() && entity instanceof class_1687) continue;
                if (entity instanceof class_1685) {
                    class_1685 trident = (class_1685)entity;
                    if (trident.field_5960) continue;
                }
                this.calculateFiredPath(entity, tickDelta);
                for (Path path : this.paths) {
                    path.render(event);
                }
            }
        }
    }

    private class Path {
        private final List<Vector3d> points = new ArrayList<Vector3d>();
        private boolean hitQuad;
        private boolean hitQuadHorizontal;
        private double hitQuadX1;
        private double hitQuadY1;
        private double hitQuadZ1;
        private double hitQuadX2;
        private double hitQuadY2;
        private double hitQuadZ2;
        private final List<class_1297> collidingEntities = new ArrayList<class_1297>();
        public Vector3d lastPoint;
        private int start;

        private Path() {
        }

        public void clear() {
            Trajectories.this.vec3s.freeAll(this.points);
            this.points.clear();
            this.hitQuad = false;
            this.collidingEntities.clear();
            this.lastPoint = null;
            this.start = 0;
        }

        public Path calculate() {
            this.addPoint();
            for (int i = 0; i < (Trajectories.this.simulationSteps.get() > 0 ? Trajectories.this.simulationSteps.get() : Integer.MAX_VALUE); ++i) {
                SimulationStep result = Trajectories.this.simulator.tick();
                this.processHitResults(result);
                if (result.shouldStop) break;
                this.addPoint();
            }
            return this;
        }

        public Path setStart(class_1297 entity, double tickDelta) {
            this.lastPoint = new Vector3d(class_3532.method_16436((double)tickDelta, (double)entity.field_6038, (double)entity.method_23317()), class_3532.method_16436((double)tickDelta, (double)entity.field_5971, (double)entity.method_23318()), class_3532.method_16436((double)tickDelta, (double)entity.field_5989, (double)entity.method_23321()));
            return this;
        }

        private void addPoint() {
            this.points.add(Trajectories.this.vec3s.get().set((Vector3dc)Trajectories.this.simulator.pos));
        }

        private void processHitResults(SimulationStep step) {
            for (int i = 0; i < step.hitResults.length; ++i) {
                class_239 result = step.hitResults[i];
                if (result.method_17783() == class_239.class_240.field_1332) {
                    class_3965 r = (class_3965)result;
                    this.hitQuad = true;
                    this.hitQuadX1 = r.method_17784().field_1352;
                    this.hitQuadY1 = r.method_17784().field_1351;
                    this.hitQuadZ1 = r.method_17784().field_1350;
                    this.hitQuadX2 = r.method_17784().field_1352;
                    this.hitQuadY2 = r.method_17784().field_1351;
                    this.hitQuadZ2 = r.method_17784().field_1350;
                    if (r.method_17780() == class_2350.field_11036 || r.method_17780() == class_2350.field_11033) {
                        this.hitQuadHorizontal = true;
                        this.hitQuadX1 -= 0.25;
                        this.hitQuadZ1 -= 0.25;
                        this.hitQuadX2 += 0.25;
                        this.hitQuadZ2 += 0.25;
                    } else if (r.method_17780() == class_2350.field_11043 || r.method_17780() == class_2350.field_11035) {
                        this.hitQuadHorizontal = false;
                        this.hitQuadX1 -= 0.25;
                        this.hitQuadY1 -= 0.25;
                        this.hitQuadX2 += 0.25;
                        this.hitQuadY2 += 0.25;
                    } else {
                        this.hitQuadHorizontal = false;
                        this.hitQuadZ1 -= 0.25;
                        this.hitQuadY1 -= 0.25;
                        this.hitQuadZ2 += 0.25;
                        this.hitQuadY2 += 0.25;
                    }
                    this.points.add(Utils.set(Trajectories.this.vec3s.get(), result.method_17784()));
                    continue;
                }
                if (result.method_17783() != class_239.class_240.field_1331) continue;
                class_1297 entity = ((class_3966)result).method_17782();
                this.collidingEntities.add(entity);
                if (!step.shouldStop || i != step.hitResults.length - 1) continue;
                this.points.add(Utils.set(Trajectories.this.vec3s.get(), result.method_17784()));
            }
        }

        public void ignoreFirstTicks() {
            this.start = this.points.size() <= Trajectories.this.ignoreFirstTicks.get() ? 0 : Trajectories.this.ignoreFirstTicks.get();
        }

        public void render(Render3DEvent event) {
            for (int i = this.start; i < this.points.size(); ++i) {
                Vector3d point = this.points.get(i);
                if (this.lastPoint != null) {
                    event.renderer.line(this.lastPoint.x, this.lastPoint.y, this.lastPoint.z, point.x, point.y, point.z, Trajectories.this.lineColor.get());
                    if (Trajectories.this.renderPositionBox.get().booleanValue()) {
                        event.renderer.box(point.x - Trajectories.this.positionBoxSize.get(), point.y - Trajectories.this.positionBoxSize.get(), point.z - Trajectories.this.positionBoxSize.get(), point.x + Trajectories.this.positionBoxSize.get(), point.y + Trajectories.this.positionBoxSize.get(), point.z + Trajectories.this.positionBoxSize.get(), Trajectories.this.positionSideColor.get(), Trajectories.this.positionLineColor.get(), Trajectories.this.shapeMode.get(), 0);
                    }
                }
                this.lastPoint = point;
            }
            if (this.hitQuad) {
                if (this.hitQuadHorizontal) {
                    event.renderer.sideHorizontal(this.hitQuadX1, this.hitQuadY1, this.hitQuadZ1, this.hitQuadX1 + 0.5, this.hitQuadZ1 + 0.5, Trajectories.this.sideColor.get(), Trajectories.this.lineColor.get(), Trajectories.this.shapeMode.get());
                } else {
                    event.renderer.sideVertical(this.hitQuadX1, this.hitQuadY1, this.hitQuadZ1, this.hitQuadX2, this.hitQuadY2, this.hitQuadZ2, Trajectories.this.sideColor.get(), Trajectories.this.lineColor.get(), Trajectories.this.shapeMode.get());
                }
            }
            for (class_1297 collidingEntity : this.collidingEntities) {
                double x = (collidingEntity.method_23317() - collidingEntity.field_6014) * (double)event.tickDelta;
                double y = (collidingEntity.method_23318() - collidingEntity.field_6036) * (double)event.tickDelta;
                double z = (collidingEntity.method_23321() - collidingEntity.field_5969) * (double)event.tickDelta;
                class_238 box = collidingEntity.method_5829();
                event.renderer.box(x + box.field_1323, y + box.field_1322, z + box.field_1321, x + box.field_1320, y + box.field_1325, z + box.field_1324, Trajectories.this.sideColor.get(), Trajectories.this.lineColor.get(), Trajectories.this.shapeMode.get(), 0);
            }
        }
    }
}

