package de.thdeg.greiner.superpangworld.game.managers;

import de.thdeg.greiner.superpangworld.gameview.GameView;
import de.thdeg.greiner.superpangworld.graphics.base.Bubble;
import de.thdeg.greiner.superpangworld.graphics.base.GameObject;
import de.thdeg.greiner.superpangworld.graphics.immovable.*;
import de.thdeg.greiner.superpangworld.graphics.moveable.*;

import java.awt.*;
import java.util.LinkedList;

/**
 * The manager handling the display and passive movement of the game objects.
 */
class GameObjectManager {

    private GameView gameView;

    private LinkedList<Bubble> bubbles;
    private LinkedList<Harpoon> harpoons;

    private LevelProgressBar levelProgressBar;
    private LevelLabel levelLabel;
    private ScoreLabel scoreLabel;
    private LivesLabel livesLabel;
    private Background background;
    private PlayerObject playerObject;

    private RandomBall randomBall;
    private FollowerBall followerBall;

    private LinkedList<GameObject> gameObjects;

    /**
     * Create a manager handling the display and passive movement of the game objects.
     * @param gameView the GameView
     */
    public GameObjectManager(GameView gameView){
        this.gameView = gameView;
        gameView.setColorForBlockImage('k', Color.LIGHT_GRAY);

        bubbles = new LinkedList<>();
        harpoons = new LinkedList<>();
        gameObjects = new LinkedList<>();

        this.levelProgressBar = new LevelProgressBar(gameView);
        this.levelLabel = new LevelLabel(gameView);
        this.scoreLabel = new ScoreLabel(gameView);
        this.livesLabel = new LivesLabel(gameView);
        this.background = new Background(gameView);

        this.playerObject = new PlayerObject(gameView);

        this.randomBall = new RandomBall(gameView);
        this.followerBall = new FollowerBall(gameView, randomBall);
    }

    /**
     * Add the objects to the canvas and handle update their positions.
     */
    public void updateGameObjects(){
        gameObjects.clear();
        gameObjects.add(background);
        gameObjects.addAll(bubbles);
        gameObjects.addAll(harpoons);
        gameObjects.add(levelProgressBar);
        gameObjects.add(levelLabel);
        gameObjects.add(scoreLabel);
        gameObjects.add(livesLabel);
        gameObjects.add(playerObject);
        gameObjects.add(randomBall);
        //gameObjects.add(followerBall);

        gameObjects.forEach(gameObject ->{
            gameObject.update();
            gameObject.addToCanvas();
        });
    }

    /**
     * Get the player object.
     * @return the player
     */
    public PlayerObject getPlayerObject(){
        return playerObject;
    }

    /**
     * Get the bubbles.
     * @return the bubbles
     */
    public LinkedList<Bubble> getBubbles() {
        return bubbles;
    }

    /**
     * Get the level label.
     * @return the level label
     */
    public LevelLabel getLevelLabel(){
        return this.levelLabel;
    }

    /**
     * Get the lives label.
     * @return the lives label
     */
    public LivesLabel getLivesLabel() {
        return livesLabel;
    }

    /**
     * Get the score label.
     * @return the score label
     */
    public ScoreLabel getScoreLabel() {
        return scoreLabel;
    }

    /**
     * Get the level progress bar.
     * @return the level progress bar
     */
    public LevelProgressBar getLevelProgressBar(){
        return levelProgressBar;
    }

    /**
     * Get the harpoons.
     * @return the harpoons
     */
    public LinkedList<Harpoon> getHarpoons() {
        return harpoons;
    }

    /**
     * Adapts the position of all game objects.
     *
     * @param adaptX Adaption to the right.
     * @param adaptY Adaption downwards.
     */
    public void moveWorld(double adaptX, double adaptY) {
        for (GameObject gameObject : gameObjects) {
            if (gameObject.getClass() != LevelLabel.class
                    && gameObject.getClass() != LevelProgressBar.class
                    && gameObject.getClass() != LivesLabel.class
                    && gameObject.getClass() != ScoreLabel.class){
                gameObject.adaptPosition(adaptX, adaptY);
            }
        }
    }
}
