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

package com.hypixel.hytale.server.core.modules.entity.component;

import com.hypixel.hytale.codec.Codec;
import com.hypixel.hytale.codec.KeyedCodec;
import com.hypixel.hytale.server.core.util.PositionUtil;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.component.ComponentAccessor;
import com.hypixel.hytale.math.vector.Transform;
import com.hypixel.hytale.protocol.Direction;
import com.hypixel.hytale.protocol.Position;
import com.hypixel.hytale.server.core.modules.entity.EntityModule;
import com.hypixel.hytale.component.ComponentType;
import com.hypixel.hytale.server.core.universe.world.storage.ChunkStore;
import com.hypixel.hytale.component.Ref;
import javax.annotation.Nullable;
import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk;
import com.hypixel.hytale.protocol.ModelTransform;
import com.hypixel.hytale.math.vector.Vector3f;
import com.hypixel.hytale.math.vector.Vector3d;
import javax.annotation.Nonnull;
import com.hypixel.hytale.codec.builder.BuilderCodec;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import com.hypixel.hytale.component.Component;

public class TransformComponent implements Component<EntityStore>
{
    @Nonnull
    public static final BuilderCodec<TransformComponent> CODEC;
    @Nonnull
    private final Vector3d position;
    @Nonnull
    private final Vector3f rotation;
    @Nonnull
    private final ModelTransform sentTransform;
    @Nullable
    @Deprecated(forRemoval = true)
    private WorldChunk chunk;
    @Nullable
    private Ref<ChunkStore> chunkRef;
    
    @Nonnull
    public static ComponentType<EntityStore, TransformComponent> getComponentType() {
        return EntityModule.get().getTransformComponentType();
    }
    
    public TransformComponent() {
        this.position = new Vector3d();
        this.rotation = new Vector3f();
        this.sentTransform = new ModelTransform(new Position(), new Direction(), new Direction());
    }
    
    public TransformComponent(@Nonnull final Vector3d position, @Nonnull final Vector3f rotation) {
        this.position = new Vector3d();
        this.rotation = new Vector3f();
        this.sentTransform = new ModelTransform(new Position(), new Direction(), new Direction());
        this.position.assign(position);
        this.rotation.assign(rotation);
    }
    
    @Nonnull
    public Vector3d getPosition() {
        return this.position;
    }
    
    public void setPosition(@Nonnull final Vector3d position) {
        this.position.assign(position);
    }
    
    public void teleportPosition(@Nonnull final Vector3d position) {
        final double x = position.getX();
        if (!Double.isNaN(x)) {
            this.position.setX(x);
        }
        final double y = position.getY();
        if (!Double.isNaN(y)) {
            this.position.setY(y);
        }
        final double z = position.getZ();
        if (!Double.isNaN(z)) {
            this.position.setZ(z);
        }
    }
    
    @Nonnull
    public Vector3f getRotation() {
        return this.rotation;
    }
    
    public void setRotation(@Nonnull final Vector3f rotation) {
        this.rotation.assign(rotation);
    }
    
    @Nonnull
    public Transform getTransform() {
        return new Transform(this.position, this.rotation);
    }
    
    public void teleportRotation(@Nonnull final Vector3f rotation) {
        final float yaw = rotation.getYaw();
        if (!Float.isNaN(yaw)) {
            this.rotation.setYaw(yaw);
        }
        final float pitch = rotation.getPitch();
        if (!Float.isNaN(pitch)) {
            this.rotation.setPitch(pitch);
        }
        final float roll = rotation.getRoll();
        if (!Float.isNaN(roll)) {
            this.rotation.setRoll(roll);
        }
    }
    
    @Nonnull
    public ModelTransform getSentTransform() {
        return this.sentTransform;
    }
    
    @Nullable
    @Deprecated(forRemoval = true)
    public WorldChunk getChunk() {
        return this.chunk;
    }
    
    @Nullable
    public Ref<ChunkStore> getChunkRef() {
        return this.chunkRef;
    }
    
    public void markChunkDirty(@Nonnull final ComponentAccessor<EntityStore> componentAccessor) {
        if (this.chunkRef == null || !this.chunkRef.isValid()) {
            return;
        }
        final World world = componentAccessor.getExternalData().getWorld();
        final Store<ChunkStore> chunkStore = world.getChunkStore().getStore();
        final WorldChunk worldChunkComponent = chunkStore.getComponent(this.chunkRef, WorldChunk.getComponentType());
        assert worldChunkComponent != null;
        worldChunkComponent.markNeedsSaving();
    }
    
    public void setChunkLocation(@Nullable final Ref<ChunkStore> chunkRef, @Nullable final WorldChunk chunk) {
        this.chunkRef = chunkRef;
        this.chunk = chunk;
    }
    
    @Nonnull
    @Override
    public TransformComponent clone() {
        final TransformComponent transformComponent = new TransformComponent(this.position, this.rotation);
        final ModelTransform transform = transformComponent.sentTransform;
        PositionUtil.assign(transform.position, this.sentTransform.position);
        PositionUtil.assign(transform.bodyOrientation, this.sentTransform.bodyOrientation);
        PositionUtil.assign(transform.lookOrientation, this.sentTransform.lookOrientation);
        return transformComponent;
    }
    
    static {
        CODEC = BuilderCodec.builder(TransformComponent.class, TransformComponent::new).append(new KeyedCodec<Vector3d>("Position", Vector3d.CODEC), (o, i) -> o.position.assign(i), o -> o.position).add().append(new KeyedCodec("Rotation", Vector3f.ROTATION), (o, i) -> o.rotation.assign(i), o -> o.rotation).add().build();
    }
}
