package de.thdeg.greiner.superpangworld.graphics.moveable;

import de.thdeg.greiner.superpangworld.gameview.GameView;
import de.thdeg.greiner.superpangworld.graphics.base.Bubble;
import de.thdeg.greiner.superpangworld.graphics.base.CollidableGameObject;
import de.thdeg.greiner.superpangworld.graphics.base.Position;
import de.thdeg.greiner.superpangworld.graphics.helper.HelperValues;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


/**
 * The classic red, round bubble.
 */
public class RoundBubble extends Bubble {

    /** The pixel art for the bubble */
    private final static String RED_BUBBLE =
            "    RRRR    \n"+
                    "   RWRRRR   \n"+
                    "  RWRRRRRR  \n"+
                    " RWRRRRRRRR \n"+
                    "RWRRRRRRRRRR\n"+
                    "RWRRRRRRRRRR\n"+
                    "RWRRRRRRRRWR\n"+
                    "RRRRRRRRRWWR\n"+
                    " RRRRRRRWWR \n"+
                    "  RRRRRWWR  \n"+
                    "   RRRWWR   \n"+
                    "    RRRR    \n";

    /** The pixel art for the bubble */
    private final static String WHITE_BUBBLE =
                    "    WWWW    \n"+
                    "   WWWWWW   \n"+
                    "  WWWWWWWW  \n"+
                    " WWWWWWWWWW \n"+
                    "WWWWWWWWWWWW\n"+
                    "WWWWWWWWWWWW\n"+
                    "WWWWWWWWWWWW\n"+
                    "WWWWWWWWWWWW\n"+
                    " WWWWWWWWWW \n"+
                    "  WWWWWWWW  \n"+
                    "   WWWWWW   \n"+
                    "    WWWW    \n";

    /** Flag for switching between red and white if the ball should blink */
    private boolean redBubble;
    /** Flag, if the bubble freezes the time when destroyed */
    protected boolean timeFreeze;

    /**
     * Create a round bubble with default values.
     *
     * @param gameView the {@link GameView} to display the bubble
     * @param objectsToCollideWith the list of {@link CollidableGameObject} the bubble can collide with
     */
    public RoundBubble(GameView gameView, List<CollidableGameObject> objectsToCollideWith) {
        super(gameView,objectsToCollideWith);
        this.hitBox.width = width-20;
        this.hitBox.height = height-20;
        redBubble = true;
    }

    /**
     * Create a round bubble with set values.
     *
     * @param gameView the {@link GameView} to display the bubble
     * @param objectsToCollideWith the list of {@link CollidableGameObject} the bubble can collide with
     * @param size the object size
     * @param position the Position
     * @param spawning flag, if the bubble is spawning or not
     * @param velocity the initial velocity of the bubble
     */
    public RoundBubble(GameView gameView, ArrayList<CollidableGameObject> objectsToCollideWith, double size, Position position, boolean spawning, Point2D velocity){
        super(gameView, objectsToCollideWith, size, position, spawning, velocity);
        this.hitBox.width = (int) (width*0.8);
        this.hitBox.height = (int) (height*0.8);
        redBubble = true;
        if(size < 2.5){
            if(random.nextInt(100)<10){
                timeFreeze = true;
            }
        }
    }

    @Override
    public void destroy() {
        gameView.playSound("burst.wav",false);
        if (size > 1.25) {
            Position positionLeft = new Position(Math.max(position.x - (width/2.0/2.0), HelperValues.FRAME_BORDER_WIDTH + 2), position.y);
            Position positionRight = new Position(Math.min(position.x + width - (width/2.0/2.0), GameView.WIDTH - (2*HelperValues.FRAME_BORDER_WIDTH) -width - 2), position.y);

            Point2D.Double velocityLeft = new Point2D.Double(Math.min(this.velocity.getX(),this.velocity.getX() * -1.0),Math.min(this.velocity.getY(),this.velocity.getY() * -1.0));
            Point2D.Double velocityRight = new Point2D.Double(Math.max(this.velocity.getX(),this.velocity.getX() * -1.0),Math.min(this.velocity.getY(),this.velocity.getY() * -1.0));

            Bubble bubbleLeft = new RoundBubble(gameView, new ArrayList<>(), size/2, positionLeft, false, velocityLeft);
            Bubble bubbleRight = new RoundBubble(gameView, new ArrayList<>(), size/2, positionRight, false, velocityRight);

            gamePlayManager.addBubbles(Arrays.asList(bubbleLeft, bubbleRight));
        }else if(timeFreeze){
            gamePlayManager.freezeMovement(1000);
        }
    }

    @Override
    protected void updateHitBoxPosition() {
        hitBox.x = (int) (position.x + (width*0.1));
        hitBox.y = (int) (position.y + (width*0.1));
    }

    /**
     * Draws the bubble onto the canvas of the {@link GameView}.
     */
    @Override
    public void addToCanvas(){
        if(gameView.timerExpired("BubbleBlink"+spawnID,"Bubble"+spawnID)){
            redBubble = !redBubble;
            gameView.setTimer("BubbleBlink"+spawnID,"Bubble"+spawnID,100);
        }
        if(!timeFreeze){
            gameView.addBlockImageToCanvas(RED_BUBBLE, getPosition().x, getPosition().y,size, rotation);
        }else{
            if(redBubble){
                gameView.addBlockImageToCanvas(RED_BUBBLE, getPosition().x, getPosition().y,size, rotation);
            }else{
                gameView.addBlockImageToCanvas(WHITE_BUBBLE, getPosition().x, getPosition().y,size, rotation);
            }
        }
    }

    @Override
    public int getBurstScore() {
        switch((int)(size*100)){
            case 1000:
                return 100;
            case 500:
                return 200;
            case 250:
                return 300;
            case 125:
                return 400;
            default:
                throw new RuntimeException();
        }
    }

    @Override
    public void updateStatus() {}
}
