package de.frajul.endlessroll.entities;

import java.util.ArrayList;
import java.util.List;

import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.particles.ParticleSource;
import de.frajul.endlessroll.entities.particles.ParticleSystem;
import de.frajul.endlessroll.entities.shapes.PlayerShape;
import de.frajul.endlessroll.entities.tools.PlayerInfluenceTool;
import de.frajul.endlessroll.main.game.Timer;

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

    private final float ROTATION_SPEED = -400;
    public final float RADIUS = 0.1f;
    private final float START_X = -0.9f;
    private final float SPEED = 0.002f;

    private float startSpeed, endSpeed;
    private float speed = SPEED;

    private long currentSuperPowerDuration;
    private boolean hasSuperPower;
    private long superPowerDuration;
    private ParticleSource superPowerParticles;

    private ParticleSystem particleSystem;
    private List<PlayerInfluenceTool> influenceTools = new ArrayList<>();
    private List<Float> forces = new ArrayList<>();
    private float gravityForce;

    public Player() {
        super(PlayerShape.BALL.getTexture(), new Vector(), 0, 0);
        super.setWidth(RADIUS * 2);
        super.setHeight(RADIUS * 2);
    }

    public void reset(){

    }

    public void startSuperPower(long duration) {
        this.superPowerDuration = duration;
        currentSuperPowerDuration = 0;
        hasSuperPower = true;
        superPowerParticles = new ParticleSource(
                new Vector(super.getPosition().x, super.getPosition().y), particleSystem.superPower);
        superPowerParticles.start();
    }

    public void init(PlayerShape playerShape, float terrainEdge, float startSpeed, float endSpeed, ParticleSystem particleSystem) {
        super.setTexture(playerShape.getTexture());
        super.setToTerrain(terrainEdge);
        super.getPosition().x = START_X;
        super.setMovement(new Vector(speed, 0));
        gravityForce = 0;
        hasSuperPower = false;
        forces.clear();
        this.startSpeed = startSpeed;
        this.endSpeed = endSpeed;
        setSpeedByProgress(0);
        this.particleSystem = particleSystem;
    }

    public void setSpeedByProgress(float progress) {
        this.speed = ((endSpeed - startSpeed) * progress + startSpeed) * SPEED;
        super.getMovement().x = speed;
    }

    public void preMoveUpdate(Timer timer) {
        if (hasSuperPower && superPowerParticles != null) {
            currentSuperPowerDuration += timer.getFrameTimeSeconds();
            hasSuperPower = superPowerDuration >= currentSuperPowerDuration;
            superPowerParticles.setPosition(new Vector(super.getPosition()));
        }
        if (!hasSuperPower && superPowerParticles != null)
            superPowerParticles.kill();

        for (PlayerInfluenceTool tool : influenceTools)
            tool.influencePlayerValues(this);

        for (float force : forces)
            super.getMovement().y += force;
        super.getMovement().y += gravityForce;
    }

    public void clearAllForces() {
        forces.clear();
        gravityForce = 0;
    }

    public void manipulateAllForces(float factor) {
        for (int i = 0; i < forces.size(); i++)
            forces.set(i, forces.get(i) * factor);
        gravityForce *= factor * factor;
    }

    public void postMoveUpdate() {
        influenceTools.clear();
        forces.clear();
    }

    public float getProgress() {
        return getPosition().x - START_X;
    }

    public float getSpeed() {
        return speed;
    }

    public boolean hasSuperPower() {
        return hasSuperPower;
    }

    public void addInfluenceTool(PlayerInfluenceTool tool) {
        influenceTools.add(tool);
    }

    public void addForce(float force) {
        forces.add(force);
    }

    public void setGravityForce(float gravityForce) {
        this.gravityForce = gravityForce;
    }

    @Override
    public void move(Vector movement) {
        super.move(movement);
        rotate(movement.x * ROTATION_SPEED);
    }

}
