package org.bot;

import org.objects.WorldObject;

import java.awt.*;
import java.awt.geom.Point2D;

public class Gytebot extends WorldObject {
    private static final float RCP_FORCE_DAMPING = 8.0F;
    private Direction direction;
    private Point2D.Float velocity;
    private float angleVelocity;
    private float viewAngle;
    private boolean isReady;

    public Gytebot(Point2D.Float position, Direction direction) {
        super(position);

        this.direction = direction;
        this.velocity = new Point2D.Float();

        convertDirectionToAngle(direction);
    }

    public Gytebot(Gytebot gytebot) {
        super(new Point2D.Float());

        if (gytebot != null) {
            this.direction = gytebot.getDirection();
            this.viewAngle = gytebot.getViewAngle();
            this.angleVelocity = gytebot.getViewAngleVelocity();
            this.position.x = (gytebot.getPosition()).x;
            this.position.y = (gytebot.getPosition()).y;
        }
    }

    private float getViewAngleVelocity() {
        return this.angleVelocity;
    }

    public void updateRotation(float elapsedTime) {
        this.viewAngle += this.angleVelocity * elapsedTime * 8.0F;
        this.angleVelocity += -this.angleVelocity * elapsedTime * 8.0F;

        this.position.x += this.velocity.x * elapsedTime * 8.0F;
        this.position.y += this.velocity.y * elapsedTime * 8.0F;

        this.velocity.x += -this.velocity.x * elapsedTime * 8.0F;
        this.velocity.y += -this.velocity.y * elapsedTime * 8.0F;

        this.isReady = (FloatUtils.isZeroWithTolerance(this.angleVelocity) && FloatUtils.isZeroWithTolerance(this.velocity.x) && FloatUtils.isZeroWithTolerance(this.velocity.y));
    }

    public void turnRight() {
        switch (this.direction) {
            case NORTH:
                this.direction = Direction.WEST;
                break;
            case WEST:
                this.direction = Direction.SOUTH;
                break;
            case SOUTH:
                this.direction = Direction.EAST;
                break;
            case EAST:
                this.direction = Direction.NORTH;
                break;
            default:
                break;
        }

        this.angleVelocity = 1.5707964F;
        this.isReady = false;
    }

    public void turnLeft() {
        switch (this.direction) {
            case NORTH:
                this.direction = Direction.EAST;
                break;
            case EAST:
                this.direction = Direction.SOUTH;
                break;
            case SOUTH:
                this.direction = Direction.WEST;
                break;
            case WEST:
                this.direction = Direction.NORTH;
            default:
                break;
        }

        this.angleVelocity = -1.5707964F;

        this.isReady = false;
    }


    private void convertDirectionToAngle(Direction direction) {
        switch (direction) {
            case NORTH:
                this.viewAngle = 1.5707964F;
                break;
            case SOUTH:
                this.viewAngle = -1.5707964F;
                break;
            case EAST:
                this.viewAngle = 0.0F;
                break;
            case WEST:
                this.viewAngle = 3.1415927F;
            default:
                break;
        }

    }


    public void goForward() {
        switch (this.direction) {
            case NORTH:
                this.velocity = new Point2D.Float(0.0F, -1.0F);
                break;
            case SOUTH:
                this.velocity = new Point2D.Float(0.0F, 1.0F);
                break;
            case EAST:
                this.velocity = new Point2D.Float(-1.0F, 0.0F);
                break;
            case WEST:
                this.velocity = new Point2D.Float(1.0F, 0.0F);
                break;
            default:
                this.velocity = new Point2D.Float();
                break;
        }

        this.isReady = false;
    }


    public Point getForwardLocation() {
        switch (this.direction) {
            case NORTH:
                return new Point(Math.round(this.position.x), Math.round(this.position.y) - 1);
            case SOUTH:
                return new Point(Math.round(this.position.x), Math.round(this.position.y) + 1);
            case EAST:
                return new Point(Math.round(this.position.x) - 1, Math.round(this.position.y));
            case WEST:
                return new Point(Math.round(this.position.x) + 1, Math.round(this.position.y));
            default:
                break;
        }
        return null;
    }


    public final Direction getDirection() {
        return this.direction;
    }


    public final float getViewAngle() {
        return this.viewAngle;
    }


    public boolean isReady() {
        return this.isReady;
    }
}
