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

package com.hypixel.hytale.builtin.hytalegenerator.patterns;

import com.hypixel.hytale.codec.codecs.EnumCodec;
import com.hypixel.hytale.codec.Codec;
import java.util.Iterator;
import com.hypixel.hytale.builtin.hytalegenerator.framework.math.Calculator;
import java.util.ArrayList;
import com.hypixel.hytale.math.vector.Vector3i;
import java.util.List;
import com.hypixel.hytale.builtin.hytalegenerator.bounds.SpaceSize;
import javax.annotation.Nonnull;

public class SurfacePattern extends Pattern
{
    @Nonnull
    private final Pattern wallPattern;
    @Nonnull
    private final Pattern originPattern;
    @Nonnull
    private final SpaceSize readSpaceSize;
    @Nonnull
    private final List<Vector3i> surfacePositions;
    @Nonnull
    private final List<Vector3i> originPositions;
    
    public SurfacePattern(@Nonnull final Pattern surfacePattern, @Nonnull final Pattern originPattern, final double surfaceRadius, final double originRadius, @Nonnull final Facing facing, final int surfaceGap, final int originGap) {
        this.wallPattern = surfacePattern;
        this.originPattern = originPattern;
        final int surfaceY = -1 - surfaceGap;
        this.surfacePositions = new ArrayList<Vector3i>(1);
        for (int x = -(int)surfaceRadius - 1; x <= (int)surfaceRadius + 1; ++x) {
            for (int z = -(int)surfaceRadius - 1; z <= (int)surfaceRadius + 1; ++z) {
                if (Calculator.distance(x, z, 0.0, 0.0) <= surfaceRadius) {
                    final Vector3i position = new Vector3i(x, surfaceY, z);
                    this.surfacePositions.add(position);
                }
            }
        }
        final int originY = originGap;
        this.originPositions = new ArrayList<Vector3i>(1);
        for (int x2 = -(int)originRadius - 1; x2 <= (int)originRadius + 1; ++x2) {
            for (int z2 = -(int)originRadius - 1; z2 <= (int)originRadius + 1; ++z2) {
                if (Calculator.distance(x2, z2, 0.0, 0.0) <= originRadius) {
                    final Vector3i position2 = new Vector3i(x2, originY, z2);
                    this.originPositions.add(position2);
                }
            }
        }
        for (final Vector3i pos : this.surfacePositions) {
            this.applyFacing(pos, facing);
        }
        for (final Vector3i pos : this.originPositions) {
            this.applyFacing(pos, facing);
        }
        SpaceSize floorSpace = surfacePattern.readSpace();
        for (final Vector3i pos2 : this.surfacePositions) {
            floorSpace = SpaceSize.merge(floorSpace, new SpaceSize(pos2));
        }
        floorSpace = SpaceSize.stack(floorSpace, surfacePattern.readSpace());
        SpaceSize originSpace = originPattern.readSpace();
        for (final Vector3i pos3 : this.originPositions) {
            originSpace = SpaceSize.merge(originSpace, new SpaceSize(pos3));
        }
        originSpace = SpaceSize.stack(originSpace, originPattern.readSpace());
        this.readSpaceSize = SpaceSize.merge(floorSpace, originSpace);
    }
    
    private void applyFacing(@Nonnull final Vector3i pos, @Nonnull final Facing facing) {
        switch (facing.ordinal()) {
            case 1: {
                this.toD(pos);
                break;
            }
            case 2: {
                this.toE(pos);
                break;
            }
            case 3: {
                this.toW(pos);
                break;
            }
            case 5: {
                this.toN(pos);
                break;
            }
            case 4: {
                this.toS(pos);
                break;
            }
        }
    }
    
    private void toD(@Nonnull final Vector3i pos) {
        pos.y = -pos.y;
    }
    
    private void toN(@Nonnull final Vector3i pos) {
        final int y = pos.y;
        pos.y = pos.z;
        pos.z = y;
    }
    
    private void toS(@Nonnull final Vector3i pos) {
        this.toN(pos);
        pos.z = -pos.z;
    }
    
    private void toW(@Nonnull final Vector3i pos) {
        final int y = pos.y;
        pos.y = -pos.x;
        pos.x = y;
    }
    
    private void toE(@Nonnull final Vector3i pos) {
        this.toW(pos);
        pos.x = -pos.x;
    }
    
    @Override
    public boolean matches(@Nonnull final Context context) {
        final Vector3i childPosition = context.position.clone();
        final Context childContext = new Context(context);
        childContext.position = childPosition;
        for (final Vector3i pos : this.originPositions) {
            childPosition.assign(pos).add(context.position);
            if (!this.originPattern.matches(childContext)) {
                return false;
            }
        }
        for (final Vector3i pos : this.surfacePositions) {
            childPosition.assign(pos).add(context.position);
            if (!this.wallPattern.matches(childContext)) {
                return false;
            }
        }
        return true;
    }
    
    @Nonnull
    @Override
    public SpaceSize readSpace() {
        return this.readSpaceSize.clone();
    }
    
    public enum Facing
    {
        U, 
        D, 
        E, 
        W, 
        S, 
        N;
        
        @Nonnull
        public static Codec<Facing> CODEC;
        
        static {
            Facing.CODEC = new EnumCodec<Facing>(Facing.class, EnumCodec.EnumStyle.LEGACY);
        }
    }
}
