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 u, @Nullable final TreeNodePosition ag2, @Nullable final TreeNodePosition ag3, final int integer4, final int integer5) {
        this.children = Lists.newArrayList();
        if (u.getDisplay() == null) {
            throw new IllegalArgumentException("Can't position an invisible advancement!");
        }
        this.advancement = u;
        this.parent = ag2;
        this.previousSibling = ag3;
        this.childIndex = integer4;
        this.ancestor = this;
        this.x = integer5;
        this.y = -1.0f;
        TreeNodePosition ag4 = null;
        for (final Advancement u2 : u.getChildren()) {
            ag4 = this.addChild(u2, ag4);
        }
    }
    
    @Nullable
    private TreeNodePosition addChild(final Advancement u, @Nullable TreeNodePosition ag) {
        if (u.getDisplay() != null) {
            ag = new TreeNodePosition(u, this, ag, this.children.size() + 1, this.x + 1);
            this.children.add(ag);
        }
        else {
            for (final Advancement u2 : u.getChildren()) {
                ag = this.addChild(u2, ag);
            }
        }
        return ag;
    }
    
    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 ag2 = null;
        for (final TreeNodePosition ag3 : this.children) {
            ag3.firstWalk();
            ag2 = ag3.apportion((ag2 == null) ? ag3 : ag2);
        }
        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 ag6 : this.children) {
            float3 = ag6.secondWalk(float1 + this.mod, integer + 1, float3);
        }
        return float3;
    }
    
    private void thirdWalk(final float float1) {
        this.y += float1;
        for (final TreeNodePosition ag4 : this.children) {
            ag4.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 ag5 = treeNodePosition = this.children.get(integer4);
            treeNodePosition.y += float2;
            final TreeNodePosition treeNodePosition2 = ag5;
            treeNodePosition2.mod += float2;
            float3 += ag5.change;
            float2 += ag5.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 ag) {
        if (this.previousSibling == null) {
            return ag;
        }
        TreeNodePosition ag2 = this;
        TreeNodePosition ag3 = this;
        TreeNodePosition ag4 = this.previousSibling;
        TreeNodePosition ag5 = this.parent.children.get(0);
        float float7 = this.mod;
        float float8 = this.mod;
        float float9 = ag4.mod;
        float float10 = ag5.mod;
        while (ag4.nextOrThread() != null && ag2.previousOrThread() != null) {
            ag4 = ag4.nextOrThread();
            ag2 = ag2.previousOrThread();
            ag5 = ag5.previousOrThread();
            ag3 = ag3.nextOrThread();
            ag3.ancestor = this;
            final float float11 = ag4.y + float9 - (ag2.y + float7) + 1.0f;
            if (float11 > 0.0f) {
                ag4.getAncestor(this, ag).moveSubtree(this, float11);
                float7 += float11;
                float8 += float11;
            }
            float9 += ag4.mod;
            float7 += ag2.mod;
            float10 += ag5.mod;
            float8 += ag3.mod;
        }
        if (ag4.nextOrThread() != null && ag3.nextOrThread() == null) {
            ag3.thread = ag4.nextOrThread();
            final TreeNodePosition treeNodePosition = ag3;
            treeNodePosition.mod += float9 - float8;
        }
        else {
            if (ag2.previousOrThread() != null && ag5.previousOrThread() == null) {
                ag5.thread = ag2.previousOrThread();
                final TreeNodePosition treeNodePosition2 = ag5;
                treeNodePosition2.mod += float7 - float10;
            }
            ag = this;
        }
        return ag;
    }
    
    private void moveSubtree(final TreeNodePosition ag, final float float2) {
        final float float3 = (float)(ag.childIndex - this.childIndex);
        if (float3 != 0.0f) {
            ag.change -= float2 / float3;
            this.change += float2 / float3;
        }
        ag.shift += float2;
        ag.y += float2;
        ag.mod += float2;
    }
    
    private TreeNodePosition getAncestor(final TreeNodePosition ag1, final TreeNodePosition ag2) {
        if (this.ancestor != null && ag1.parent.children.contains(this.ancestor)) {
            return this.ancestor;
        }
        return ag2;
    }
    
    private void finalizePosition() {
        if (this.advancement.getDisplay() != null) {
            this.advancement.getDisplay().setLocation((float)this.x, this.y);
        }
        if (!this.children.isEmpty()) {
            for (final TreeNodePosition ag3 : this.children) {
                ag3.finalizePosition();
            }
        }
    }
    
    public static void run(final Advancement u) {
        if (u.getDisplay() == null) {
            throw new IllegalArgumentException("Can't position children of an invisible root!");
        }
        final TreeNodePosition ag2 = new TreeNodePosition(u, null, null, 1, 0);
        ag2.firstWalk();
        final float float3 = ag2.secondWalk(0.0f, 0, ag2.y);
        if (float3 < 0.0f) {
            ag2.thirdWalk(-float3);
        }
        ag2.finalizePosition();
    }
}
