package net.minecraft.advancements;

import java.util.Iterator;
import com.google.common.collect.Lists;
import javax.annotation.Nullable;
import java.util.List;

public class TreeNodePosition {
    private final Advancement advancement;
    private final TreeNodePosition parent;
    private final TreeNodePosition previousSibling;
    private final int childIndex;
    private final List<TreeNodePosition> children;
    private TreeNodePosition ancestor;
    private TreeNodePosition thread;
    private int x;
    private float y;
    private float mod;
    private float change;
    private float shift;
    
    public TreeNodePosition(final Advancement w, @Nullable final TreeNodePosition ai2, @Nullable final TreeNodePosition ai3, final int integer4, final int integer5) {
        this.children = Lists.newArrayList();
        if (w.getDisplay() == null) {
            throw new IllegalArgumentException("Can't position an invisible advancement!");
        }
        this.advancement = w;
        this.parent = ai2;
        this.previousSibling = ai3;
        this.childIndex = integer4;
        this.ancestor = this;
        this.x = integer5;
        this.y = -1.0f;
        TreeNodePosition ai4 = null;
        for (final Advancement w2 : w.getChildren()) {
            ai4 = this.addChild(w2, ai4);
        }
    }
    
    @Nullable
    private TreeNodePosition addChild(final Advancement w, @Nullable TreeNodePosition ai) {
        if (w.getDisplay() != null) {
            ai = new TreeNodePosition(w, this, ai, this.children.size() + 1, this.x + 1);
            this.children.add(ai);
        }
        else {
            for (final Advancement w2 : w.getChildren()) {
                ai = this.addChild(w2, ai);
            }
        }
        return ai;
    }
    
    private void firstWalk() {
        if (this.children.isEmpty()) {
            if (this.previousSibling != null) {
                this.y = this.previousSibling.y + 1.0f;
            }
            else {
                this.y = 0.0f;
            }
            return;
        }
        TreeNodePosition ai2 = null;
        for (final TreeNodePosition ai3 : this.children) {
            ai3.firstWalk();
            ai2 = ai3.apportion((ai2 == null) ? ai3 : ai2);
        }
        this.executeShifts();
        final float float3 = (this.children.get(0).y + this.children.get(this.children.size() - 1).y) / 2.0f;
        if (this.previousSibling != null) {
            this.y = this.previousSibling.y + 1.0f;
            this.mod = this.y - float3;
        }
        else {
            this.y = float3;
        }
    }
    
    private float secondWalk(final float float1, final int integer, float float3) {
        this.y += float1;
        this.x = integer;
        if (this.y < float3) {
            float3 = this.y;
        }
        for (final TreeNodePosition ai6 : this.children) {
            float3 = ai6.secondWalk(float1 + this.mod, integer + 1, float3);
        }
        return float3;
    }
    
    private void thirdWalk(final float float1) {
        this.y += float1;
        for (final TreeNodePosition ai4 : this.children) {
            ai4.thirdWalk(float1);
        }
    }
    
    private void executeShifts() {
        float float2 = 0.0f;
        float float3 = 0.0f;
        for (int integer4 = this.children.size() - 1; integer4 >= 0; --integer4) {
            final TreeNodePosition treeNodePosition;
            final TreeNodePosition ai5 = treeNodePosition = this.children.get(integer4);
            treeNodePosition.y += float2;
            final TreeNodePosition treeNodePosition2 = ai5;
            treeNodePosition2.mod += float2;
            float3 += ai5.change;
            float2 += ai5.shift + float3;
        }
    }
    
    @Nullable
    private TreeNodePosition previousOrThread() {
        if (this.thread != null) {
            return this.thread;
        }
        if (!this.children.isEmpty()) {
            return this.children.get(0);
        }
        return null;
    }
    
    @Nullable
    private TreeNodePosition nextOrThread() {
        if (this.thread != null) {
            return this.thread;
        }
        if (!this.children.isEmpty()) {
            return this.children.get(this.children.size() - 1);
        }
        return null;
    }
    
    private TreeNodePosition apportion(TreeNodePosition ai) {
        if (this.previousSibling == null) {
            return ai;
        }
        TreeNodePosition ai2 = this;
        TreeNodePosition ai3 = this;
        TreeNodePosition ai4 = this.previousSibling;
        TreeNodePosition ai5 = this.parent.children.get(0);
        float float7 = this.mod;
        float float8 = this.mod;
        float float9 = ai4.mod;
        float float10 = ai5.mod;
        while (ai4.nextOrThread() != null && ai2.previousOrThread() != null) {
            ai4 = ai4.nextOrThread();
            ai2 = ai2.previousOrThread();
            ai5 = ai5.previousOrThread();
            ai3 = ai3.nextOrThread();
            ai3.ancestor = this;
            final float float11 = ai4.y + float9 - (ai2.y + float7) + 1.0f;
            if (float11 > 0.0f) {
                ai4.getAncestor(this, ai).moveSubtree(this, float11);
                float7 += float11;
                float8 += float11;
            }
            float9 += ai4.mod;
            float7 += ai2.mod;
            float10 += ai5.mod;
            float8 += ai3.mod;
        }
        if (ai4.nextOrThread() != null && ai3.nextOrThread() == null) {
            ai3.thread = ai4.nextOrThread();
            final TreeNodePosition treeNodePosition = ai3;
            treeNodePosition.mod += float9 - float8;
        }
        else {
            if (ai2.previousOrThread() != null && ai5.previousOrThread() == null) {
                ai5.thread = ai2.previousOrThread();
                final TreeNodePosition treeNodePosition2 = ai5;
                treeNodePosition2.mod += float7 - float10;
            }
            ai = this;
        }
        return ai;
    }
    
    private void moveSubtree(final TreeNodePosition ai, final float float2) {
        final float float3 = (float)(ai.childIndex - this.childIndex);
        if (float3 != 0.0f) {
            ai.change -= float2 / float3;
            this.change += float2 / float3;
        }
        ai.shift += float2;
        ai.y += float2;
        ai.mod += float2;
    }
    
    private TreeNodePosition getAncestor(final TreeNodePosition ai1, final TreeNodePosition ai2) {
        if (this.ancestor != null && ai1.parent.children.contains(this.ancestor)) {
            return this.ancestor;
        }
        return ai2;
    }
    
    private void finalizePosition() {
        if (this.advancement.getDisplay() != null) {
            this.advancement.getDisplay().setLocation((float)this.x, this.y);
        }
        if (!this.children.isEmpty()) {
            for (final TreeNodePosition ai3 : this.children) {
                ai3.finalizePosition();
            }
        }
    }
    
    public static void run(final Advancement w) {
        if (w.getDisplay() == null) {
            throw new IllegalArgumentException("Can't position children of an invisible root!");
        }
        final TreeNodePosition ai2 = new TreeNodePosition(w, null, null, 1, 0);
        ai2.firstWalk();
        final float float3 = ai2.secondWalk(0.0f, 0, ai2.y);
        if (float3 < 0.0f) {
            ai2.thirdWalk(-float3);
        }
        ai2.finalizePosition();
    }
}
