package de.frajul.endlessroll.main.game;

import de.frajul.endlessroll.data.Vector;
import de.frajul.endlessroll.entities.DestroyEffect;
import de.frajul.endlessroll.entities.Goal;
import de.frajul.endlessroll.entities.Obstacle;
import de.frajul.endlessroll.entities.collectables.Energy;
import de.frajul.endlessroll.entities.collectables.Star;
import de.frajul.endlessroll.entities.collision.CollisionDetector;
import de.frajul.endlessroll.entities.particles.ParticleSystem;
import de.frajul.endlessroll.entities.shapes.PlayerShape;
import de.frajul.endlessroll.entities.textures.TexturePack;
import de.frajul.endlessroll.entities.tools.Bomb;
import de.frajul.endlessroll.entities.tools.Tool;
import de.frajul.endlessroll.entities.tools.ToolType;
import de.frajul.endlessroll.levels.Level;
import de.frajul.endlessroll.levels.ObstacleData;
import de.frajul.endlessroll.levels.worlds.World;
import de.frajul.endlessroll.main.GameLog;
import de.frajul.endlessroll.main.physics.Physics;

/**
 * Created by Julian on 27.11.2015.
 */
public class GameScene extends Scene {

    private World currentWorld;
    private CollisionDetector collisionDetector;
    private Goal goal;
    private float goalX;

    public GameScene(TexturePack texturePack, ParticleSystem particleSystem) throws Exception {
        super(texturePack, particleSystem);
        collisionDetector = new CollisionDetector();

        goal = new Goal(textures.goal);
    }

    public void loadLevel(Level level, World world, PlayerShape playerPlayerShape) throws Exception {
        this.currentWorld = world;
        super.reset();
        background.changeTexture(world.getBackgroundTexture());
        terrain.loadData(world, level.getTerrainEdge(), level.getTerrainTiles());
        ceiling.loadData(world, level.getCeilingEdge(), level.getCeilingTiles());
        uncategorizedEntities.add(goal);
        player.init(playerPlayerShape, terrain.getEdge(), level.getStartSpeed(), level.getEndSpeed(), particleSystem);
        uncategorizedEntities.add(player);
        collectables.init(level, textures);
        for (ObstacleData data : level.getObstacles())
            addObstacle(data);

        goalX = level.getGoalX();
        goal.setGoalX(goalX);
        GameLog.d("Level " + level.getId() + " successfully loaded");
    }

    public void onStarCollision(Star collisionStar) {
        collisionStar.destroy(DestroyEffect.STAR_EXPLOSION);
    }

    public void onEnergyCollision(Energy energy) {
        energy.destroy(DestroyEffect.ENERGY_COLLECT);
    }

    public void addObstacle(ObstacleData data) {
        Obstacle obstacle = new Obstacle(currentWorld, data, terrain.getEdge());
        obstacles.add(obstacle);
    }

    public void addTool(ToolType type, float screenX, float screenY, Physics physics) throws Exception {
        Vector position = calcWorldFromScreenCoords(screenX, screenY);
        Tool tool = type.newInstance(position, particleSystem);
        physics.checkSingleToolCollision(tool, this);

        if (tool == null)
            throw new Exception(
                    "Current ToolType(" + type + ") returns null at method newInstance()");
        tools.add(tool);
    }


    public void update(Timer timer) {
        player.setSpeedByProgress(player.getProgress() / goalX);
        player.preMoveUpdate(timer);

        if (player.hasSuperPower() && player.getBottomEdge() < terrain.getEdge()) {
            player.setToTerrain(terrain.getEdge());
            if (player.getMovement().y < 0)
                player.getMovement().setY(0);
        }

        super.update(timer);

        player.postMoveUpdate();

        synchronized (tools) {
            for (Tool tool : tools) {
                if (tool instanceof Bomb) {
                    Bomb bomb = (Bomb) tool;
                    if (bomb.isExploding())
                        bomb.explode(obstacles, collisionDetector);
                }
            }
        }

    }

    public float getGoalX() {
        return goalX;
    }

}
