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

package com.hypixel.hytale.math.shape;

import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.KeyedCodec;
import javax.annotation.Nonnull;
import com.hypixel.hytale.math.vector.Vector2d;
import com.hypixel.hytale.codec.builder.BuilderCodec;

public class Box2D implements Shape2D
{
    public static final BuilderCodec<Box2D> CODEC;
    @Nonnull
    public final Vector2d min;
    @Nonnull
    public final Vector2d max;
    
    public Box2D() {
        this.min = new Vector2d();
        this.max = new Vector2d();
    }
    
    public Box2D(@Nonnull final Box2D box) {
        this();
        this.min.assign(box.min);
        this.max.assign(box.max);
    }
    
    public Box2D(@Nonnull final Vector2d min, @Nonnull final Vector2d max) {
        this();
        this.min.assign(min);
        this.max.assign(max);
    }
    
    public Box2D(final double xMin, final double yMin, final double xMax, final double yMax) {
        this();
        this.min.assign(xMin, yMin);
        this.max.assign(xMax, yMax);
    }
    
    @Nonnull
    public Box2D setMinMax(@Nonnull final Vector2d min, @Nonnull final Vector2d max) {
        this.min.assign(min);
        this.max.assign(max);
        return this;
    }
    
    @Nonnull
    public Box2D setMinMax(@Nonnull final double[] min, @Nonnull final double[] max) {
        this.min.assign(min);
        this.max.assign(max);
        return this;
    }
    
    @Nonnull
    public Box2D setMinMax(@Nonnull final float[] min, @Nonnull final float[] max) {
        this.min.assign(min);
        this.max.assign(max);
        return this;
    }
    
    @Nonnull
    public Box2D setEmpty() {
        this.setMinMax(Double.MAX_VALUE, -1.7976931348623157E308);
        return this;
    }
    
    @Nonnull
    public Box2D setMinMax(final double min, final double max) {
        this.min.assign(min);
        this.max.assign(max);
        return this;
    }
    
    @Nonnull
    public Box2D union(@Nonnull final Box2D bb) {
        if (this.min.x > bb.min.x) {
            this.min.x = bb.min.x;
        }
        if (this.min.y > bb.min.y) {
            this.min.y = bb.min.y;
        }
        if (this.max.x < bb.max.x) {
            this.max.x = bb.max.x;
        }
        if (this.max.y < bb.max.y) {
            this.max.y = bb.max.y;
        }
        return this;
    }
    
    @Nonnull
    public Box2D assign(@Nonnull final Box2D other) {
        this.min.assign(other.min);
        this.max.assign(other.max);
        return this;
    }
    
    @Nonnull
    public Box2D minkowskiSum(@Nonnull final Box2D bb) {
        this.min.subtract(bb.max);
        this.max.subtract(bb.min);
        return this;
    }
    
    @Nonnull
    public Box2D normalize() {
        if (this.min.x > this.max.x) {
            final double t = this.min.x;
            this.min.x = this.max.x;
            this.max.x = t;
        }
        if (this.min.y > this.max.y) {
            final double t = this.min.y;
            this.min.y = this.max.y;
            this.max.y = t;
        }
        return this;
    }
    
    @Nonnull
    public Box2D offset(@Nonnull final Vector2d pos) {
        this.min.add(pos);
        this.max.add(pos);
        return this;
    }
    
    @Nonnull
    public Box2D sweep(@Nonnull final Vector2d v) {
        if (v.x < 0.0) {
            final Vector2d min = this.min;
            min.x += v.x;
        }
        else if (v.x > 0.0) {
            final Vector2d max = this.max;
            max.x += v.x;
        }
        if (v.y < 0.0) {
            final Vector2d min2 = this.min;
            min2.y += v.y;
        }
        else if (v.y > 0.0) {
            final Vector2d max2 = this.max;
            max2.y += v.y;
        }
        return this;
    }
    
    @Nonnull
    public Box2D extendToInt() {
        this.min.floor();
        this.max.ceil();
        return this;
    }
    
    @Nonnull
    public Box2D extend(final double extentX, final double extentY) {
        this.min.subtract(extentX, extentY);
        this.max.add(extentX, extentY);
        return this;
    }
    
    public double width() {
        return this.max.x - this.min.x;
    }
    
    public double height() {
        return this.max.y - this.min.y;
    }
    
    public boolean isIntersecting(@Nonnull final Box2D other) {
        return this.min.x <= other.max.x && other.min.x <= this.max.x && this.min.y <= other.max.y && other.min.y <= this.max.y;
    }
    
    @Nonnull
    @Override
    public Box2D getBox(final double x, final double y) {
        return new Box2D(this.min.getX() + x, this.min.getY() + y, this.max.getX() + x, this.max.getY() + y);
    }
    
    @Override
    public boolean containsPosition(@Nonnull final Vector2d origin, @Nonnull final Vector2d position) {
        final double x = position.getX() - origin.getX();
        final double y = position.getY() - origin.getY();
        return x >= this.min.getX() && x <= this.max.getX() && y >= this.min.getY() && y <= this.max.getY();
    }
    
    @Override
    public boolean containsPosition(@Nonnull final Vector2d origin, final double xx, final double yy) {
        final double x = xx - origin.getX();
        final double y = yy - origin.getY();
        return x >= this.min.getX() && x <= this.max.getX() && y >= this.min.getY() && y <= this.max.getY();
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "Box2D{min=" + String.valueOf(this.min) + ", max=" + String.valueOf(this.max);
    }
    
    static {
        CODEC = BuilderCodec.builder(Box2D.class, Box2D::new).append(new KeyedCodec<Vector2d>("Min", Vector2d.CODEC), (shape, min) -> shape.min.assign(min), shape -> shape.min).add().append(new KeyedCodec("Max", Vector2d.CODEC), (shape, max) -> shape.max.assign(max), shape -> shape.max).add().build();
    }
}
