package de.frajul.endlessroll.entities;

import java.util.Random;

import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.textures.Texture;
import de.frajul.endlessroll.levels.MoveComponent;
import de.frajul.endlessroll.levels.ObstacleData;
import de.frajul.endlessroll.levels.worlds.World;

/**
 * Created by Julian on 20.11.2015.
 */
public class Obstacle extends Entity {

    private boolean deadly;
    private boolean floating;
    private boolean moving;
    private final float GRID_SQUARE_SIZE = 0.1f;
    private Vector gridSize;
    private MoveComponent moveComponent;

    private Vertex zeroPoint;
    private boolean clockwise;
    private float totalMoveDistance;
    private float moveProgress;

    public Obstacle(World world, ObstacleData data, float terrainEdge) {
        super(world.getObstacleTexture(), new Vector(data.getX(), data.getY()), data.getWidth(), data.getHeight());
        this.deadly = data.isDeadly();
        this.floating = data.isFloating();
        this.moving = data.isMoving();
        this.moveComponent = data.getMoveComponent();
        if (moveComponent != null)
            moveComponent.shrink(new Vector(super.getWidth(), super.getHeight()));

        if (!floating)
            super.setToTerrain(terrainEdge);
        if (moving)
            randomMovementData();
        gridSize = calcGridSize();
    }

    private Vector calcGridSize(){
        int gridWidth = (int) (width / GRID_SQUARE_SIZE);
        int gridHeight = (int) (height / GRID_SQUARE_SIZE);
        gridWidth = Math.max(gridWidth, 2);
        gridHeight = Math.max(gridHeight, 2);
        return new Vector(gridWidth, gridHeight);
    }

    public void moveWithMoveComponent(float value) {
        float distance = value * moveComponent.getSpeed() * 0.001f;
        moveProgress += distance / totalMoveDistance;
        moveProgress %= 1.0f;
        setPositionForMoveProgress();
    }

    private void setPositionForMoveProgress() {
        float distance = 0;
        Vertex lastVertex = zeroPoint;
        while (true) {
            Vertex nextVertex = lastVertex.getNext(clockwise);
            float nextDistance = distance + (Math.abs(lastVertex.getX() - nextVertex.getX()) * 0.5f * moveComponent.getWidth()) + (Math.abs(lastVertex.getY() - nextVertex.getY()) * 0.5f * moveComponent.getHeight());
            if (nextDistance >= moveProgress * totalMoveDistance) {
                float distanceLeft = moveProgress * totalMoveDistance - distance;
                Vector direction = new Vector(nextVertex.getX(), nextVertex.getY()).translate(new Vector(lastVertex.getX(), lastVertex.getY()).negate());
                direction = direction.mul(0.5f * distanceLeft);
                super.setPosition(moveComponent.getPositionOfVertex(lastVertex).translate(direction));
                return;
            }
            distance = nextDistance;
            lastVertex = nextVertex;
        }
    }

    private void randomMovementData() {
        Random random = new Random();
        int index = random.nextInt(4);
        zeroPoint = Vertex.values()[index];
        clockwise = random.nextBoolean();
        totalMoveDistance = moveComponent.getWidth() * 2 + moveComponent.getHeight() * 2;
    }

    public boolean isMoving() {
        return moving;
    }

    public boolean isDeadly() {
        return deadly;
    }

    public boolean isFloating() {
        return floating;
    }

    public Vector getGridSize(){
        return gridSize;
    }

}
