// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.worldgen.cave.shape.distorted;

import com.hypixel.hytale.math.util.TrigMathUtil;
import com.hypixel.hytale.procedurallib.logic.GeneralNoise;
import com.hypixel.hytale.math.util.MathUtil;
import com.hypixel.hytale.server.worldgen.cave.CaveType;
import com.hypixel.hytale.procedurallib.random.CoordinateRotator;
import javax.annotation.Nonnull;
import com.hypixel.hytale.math.vector.Vector3d;

public abstract class AbstractDistortedBody extends AbstractDistortedShape
{
    @Nonnull
    protected final Vector3d o;
    protected final Vector3d v;
    @Nonnull
    protected final CoordinateRotator rotation;
    
    public AbstractDistortedBody(@Nonnull final Vector3d o, final Vector3d v, final double yaw, final double pitch, final double radiusX, final double radiusY, final double radiusZ) {
        this(o, v, new CoordinateRotator(pitch, yaw), radiusX, radiusY, radiusZ);
    }
    
    private AbstractDistortedBody(@Nonnull final Vector3d o, final Vector3d v, @Nonnull final CoordinateRotator rotation, final double radiusX, final double radiusY, final double radiusZ) {
        super(o, maxX(rotation, radiusX, radiusY, radiusZ), maxY(rotation, radiusX, radiusY, radiusZ), maxZ(rotation, radiusX, radiusY, radiusZ));
        this.o = o;
        this.v = v;
        this.rotation = rotation;
    }
    
    protected abstract double getHeight(final int p0, final double p1, final double p2, final double p3, final double p4, final CaveType p5, final ShapeDistortion p6);
    
    @Nonnull
    @Override
    public Vector3d getStart() {
        return new Vector3d(this.o.x, this.getHighBoundY(), this.o.z);
    }
    
    @Nonnull
    @Override
    public Vector3d getEnd() {
        return new Vector3d(this.o.x, this.getLowBoundY(), this.o.z);
    }
    
    @Override
    public double getHeightAtProjection(final int caveSeed, double x, double z, final double t, final double centerY, final CaveType caveType, final ShapeDistortion distortion) {
        final double dx = x - this.o.x;
        final double dz = z - this.o.z;
        x = this.o.x + this.rotation.rotateX(dx, 0.0, dz);
        z = this.o.z + this.rotation.rotateZ(dx, 0.0, dz);
        return this.getHeight(caveSeed, x, z, t, centerY, caveType, distortion);
    }
    
    @Override
    public double getFloor(final double x, final double z, final double centerY, final double height) {
        final double dx = x - this.o.x;
        final double dz = z - this.o.z;
        final double dy = this.rotation.rotateY(dx, -height, dz);
        return centerY + dy;
    }
    
    @Override
    public double getCeiling(final double x, final double z, final double centerY, final double height) {
        final double dx = x - this.o.x;
        final double dz = z - this.o.z;
        final double dy = this.rotation.rotateY(dx, height, dz);
        return centerY + dy;
    }
    
    private static double maxX(@Nonnull final CoordinateRotator rotation, final double radiusX, final double radiusY, final double radiusZ) {
        final double x1 = Math.abs(rotation.rotateX(radiusX, radiusY, radiusZ));
        final double x2 = Math.abs(rotation.rotateX(-radiusX, radiusY, radiusZ));
        return MathUtil.maxValue(x1, x2);
    }
    
    private static double maxY(@Nonnull final CoordinateRotator rotation, final double radiusX, final double radiusY, final double radiusZ) {
        final double y1 = Math.abs(rotation.rotateY(radiusX, radiusY, radiusZ));
        final double y2 = Math.abs(rotation.rotateY(radiusX, -radiusY, radiusZ));
        return Math.max(y1, y2);
    }
    
    private static double maxZ(@Nonnull final CoordinateRotator rotation, final double radiusX, final double radiusY, final double radiusZ) {
        final double z1 = Math.abs(rotation.rotateZ(radiusX, radiusY, radiusZ));
        final double z2 = Math.abs(rotation.rotateZ(radiusX, radiusY, -radiusZ));
        return MathUtil.maxValue(z1, z2);
    }
    
    protected abstract static class Factory implements DistortedShape.Factory
    {
        @Override
        public DistortedShape create(final Vector3d origin, @Nonnull final Vector3d direction, final double length, final double startWidth, final double startHeight, final double midWidth, final double midHeight, final double endWidth, final double endHeight, final GeneralNoise.InterpolationFunction interpolation) {
            final double scale = 1.0 / direction.length();
            final double nx = direction.x * scale;
            final double ny = direction.y * scale;
            final double nz = direction.z * scale;
            final double yaw = TrigMathUtil.atan2(nx, nz);
            final double pitch = TrigMathUtil.asin(-ny);
            return this.createShape(origin, direction, yaw, pitch, startWidth, startHeight, length, interpolation);
        }
        
        protected abstract DistortedShape createShape(final Vector3d p0, final Vector3d p1, final double p2, final double p3, final double p4, final double p5, final double p6, final GeneralNoise.InterpolationFunction p7);
    }
}
