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

package com.hypixel.hytale.builtin.hytalegenerator.density.nodes;

import com.hypixel.hytale.builtin.hytalegenerator.VectorUtil;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.hypixel.hytale.math.vector.Vector3d;
import com.hypixel.hytale.builtin.hytalegenerator.density.Density;

public class RotatorDensity extends Density
{
    private static final Vector3d Y_AXIS;
    @Nullable
    private Density input;
    private Vector3d rotationAxis;
    private Vector3d tiltAxis;
    private double tiltAngle;
    private final double spinAngle;
    @Nonnull
    private final SpecialCase axisSpecialCase;
    
    public RotatorDensity(@Nonnull final Density input, @Nonnull final Vector3d newYAxis, final double spinAngle) {
        this.input = input;
        this.spinAngle = spinAngle * 3.141592653589793 / 180.0;
        final Vector3d yAxis = new Vector3d(0.0, 1.0, 0.0);
        this.rotationAxis = newYAxis.cross(yAxis);
        if (this.rotationAxis.length() < 1.0E-8) {
            this.rotationAxis = yAxis;
            if (newYAxis.dot(yAxis) < 0.0) {
                this.axisSpecialCase = SpecialCase.INVERTED_Y_AXIS;
            }
            else {
                this.axisSpecialCase = SpecialCase.Y_AXIS;
            }
        }
        else {
            this.axisSpecialCase = SpecialCase.NONE;
        }
        this.rotationAxis.normalize();
        if (this.axisSpecialCase == SpecialCase.INVERTED_Y_AXIS || this.axisSpecialCase == SpecialCase.Y_AXIS) {
            this.tiltAxis = new Vector3d();
            this.tiltAngle = 0.0;
        }
        this.tiltAxis = yAxis.cross(newYAxis);
        this.tiltAngle = Math.acos(newYAxis.dot(yAxis) / (newYAxis.length() * yAxis.length()));
    }
    
    @Override
    public double process(@Nonnull final Context context) {
        if (this.input == null) {
            return 0.0;
        }
        final Vector3d childPosition = context.position.clone();
        switch (this.axisSpecialCase.ordinal()) {
            case 2: {
                childPosition.scale(-1.0);
            }
            case 0: {
                VectorUtil.rotateAroundAxis(childPosition, this.tiltAxis, this.tiltAngle);
                break;
            }
        }
        VectorUtil.rotateAroundAxis(childPosition, RotatorDensity.Y_AXIS, this.spinAngle);
        final Context childContext = new Context(context);
        childContext.position = childPosition;
        return this.input.process(childContext);
    }
    
    @Override
    public void setInputs(@Nonnull final Density[] inputs) {
        if (inputs.length == 0) {
            this.input = null;
        }
        this.input = inputs[0];
    }
    
    static {
        Y_AXIS = new Vector3d(0.0, 1.0, 0.0);
    }
    
    private enum SpecialCase
    {
        NONE, 
        Y_AXIS, 
        INVERTED_Y_AXIS;
    }
}
