package com.hyperling.apps.games;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

import java.util.ArrayList;

/**
 * Created by ling on 12/28/16.
 */

public class BirdGameView extends GameView {
    private final String birdScoreKey;

    private final int birdGameSpeed = -8;
    private final int birdEnemySpeedVariance = 5;
    private final int birdEnemySpeedConstant = 2;
    private final int cloudsSpeed = birdGameSpeed/2;

    private Bird bird;
    private Bitmap birdBitmap;

    private ArrayList<BirdEnemy> birdEnemies;
    private Bitmap birdEnemyBitmap;

    private final int birdWidth = 30;
    private final int birdHeight = 20;
    private final int birdFrames = 4;

    private ArrayList<ExtraLife> birdExtraLives;
    private Bitmap birdExtraLifeBitmap;

    private final int birdExtraLifeWidth = 20;
    private final int birdExtraLifeHeight = 30;

    private final int birdMaxNumEnemyRows = HEIGHT / birdHeight;
    private final int birdEnemySpawnRate = 25;

    private Bitmap backgroundBitmap, cloudsBitmap;

    public BirdGameView(Context context){
        super(context);

        // Keys
        birdScoreKey = resources.getString(R.string.birdScoreKey);
    }

    private void displayScore(Canvas canvas){
        int highScore = sharedPreferences.getInt(birdScoreKey, 0);
        textPaint.setColor(Color.parseColor("#330066"));
        canvas.drawText("High: " + highScore, 0, textPaint.getTextSize(), textPaint);
        canvas.drawText("Current: " + bird.getScore(), 0, textPaint.getTextSize() * 2, textPaint);

        if (bird.getLives() > 0) {
            canvas.drawText("Lives: " + bird.getLives(), 0, textPaint.getTextSize() * 3, textPaint);
        }

        if (fpsEnabled){
            canvas.drawText("FPS: " + thread.averageFPS, 0, HEIGHT - 1, textPaint);
        }

        if (!bird.isPlaying()) {
            textPaint.setColor(Color.parseColor("#330066"));
            canvas.drawText("You are the Purple Bird", WIDTH / 4, HEIGHT / 4 - textPaint.getTextSize(), textPaint);

            textPaint.setColor(Color.parseColor("#FF9900"));
            canvas.drawText("Tap the Screen to Start", WIDTH / 4, HEIGHT / 4, textPaint);
            canvas.drawText("Hold the Screen to Fly Higher", WIDTH / 4, HEIGHT / 4 + textPaint.getTextSize(), textPaint);

            textPaint.setColor(Color.parseColor("#FF0000"));
            canvas.drawText("Dodge the Enemy Birds", WIDTH / 4, HEIGHT * 3 / 4, textPaint);

            textPaint.setColor(Color.parseColor("#FFFF00"));
            textPaint.setFakeBoldText(true);
            canvas.drawText("Collect the Bird Coins for Extra Lives", WIDTH / 4, HEIGHT * 3 / 4 + textPaint.getTextSize(), textPaint);
            textPaint.setFakeBoldText(false);
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {

        // Base Object Initializations
        if (higherQualityEnabled) {
            backgroundBitmap = BitmapFactory.decodeResource(resources, R.drawable.background_forest_without_clouds);
            cloudsBitmap = BitmapFactory.decodeResource(resources, R.drawable.clouds);
        }
        else{
            backgroundBitmap = BitmapFactory.decodeResource(resources, R.drawable.background_forest);
        }
        birdBitmap = BitmapFactory.decodeResource(resources, R.drawable.bird);
        birdEnemyBitmap = BitmapFactory.decodeResource(resources, R.drawable.bird_enemy);
        birdExtraLifeBitmap = BitmapFactory.decodeResource(resources, R.drawable.bird_extra_life);

        // Game Object Initializations
        background = new GameBackground(backgroundBitmap);
        if (higherQualityEnabled) {
            clouds = new GameBackground(cloudsBitmap);
        }
        bird = new Bird(birdBitmap, birdWidth, birdHeight, birdFrames);
        birdEnemies = new ArrayList<>();
        birdExtraLives = new ArrayList<>();

        // Settings
        setGameSpeed(birdGameSpeed);

        super.surfaceCreated(holder);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (!bird.isPlaying()) {
                bird.setPlaying(true);

                int lifeMiddleOfScreen = HEIGHT/2 - birdExtraLifeHeight/2;
                birdExtraLives.add(new ExtraLife(birdExtraLifeBitmap, birdExtraLifeWidth, birdExtraLifeHeight, WIDTH, lifeMiddleOfScreen, 1));
            }
            else{
                bird.setFlapping(true);
            }

            return true;
        }

        if (event.getAction() == MotionEvent.ACTION_UP){
            bird.setFlapping(false);

            return true;
        }

        return super.onTouchEvent(event);
    }

    public void pauseGame() {
        super.pauseGame(birdScoreKey, bird.getScore());
    }

    @Override
    public void update() {
        super.update();


        if (bird.isPlaying()) {
            background.update(gameSpeed);
            if (higherQualityEnabled) {
                clouds.update(cloudsSpeed);
            }

            int birdLevel = bird.getScore() / (birdEnemySpawnRate * birdMaxNumEnemyRows);

            // Update extra lives before enemies :)
            for (int i = 0; i < birdExtraLives.size(); i++) {
                ExtraLife birdExtraLife = birdExtraLives.get(i);
                boolean removeLife = false;

                // Check if we've hit any extra lives
                if (bird.getRect().intersect(birdExtraLife.getRect())){
                    bird.addLives(birdExtraLife.getNumLives());
                    removeLife = true;
                }

                if (removeLife || birdExtraLife.x + birdExtraLifeWidth < 0){
                    birdExtraLives.remove(birdExtraLife);
                    i--;
                }
                else{
                    birdExtraLife.update(birdGameSpeed);
                }
            }

            /***** Add new lives *****/
            // Only < so that lives don't appear until more than 1 bird can be on a row
            if (birdExtraLives.size() < birdLevel){
                int birdExtraLifeX = WIDTH + birdExtraLifeWidth;
                int birdExtraLifeY = ((int)(Math.random() * HEIGHT));;
                birdExtraLives.add(new ExtraLife(birdExtraLifeBitmap, birdExtraLifeWidth, birdExtraLifeHeight, birdExtraLifeX, birdExtraLifeY, 1));
            }

            // Update enemies
            for (int i = 0; i < birdEnemies.size(); i++){
                BirdEnemy birdEnemy = birdEnemies.get(i);
                boolean birdEnemyRemove = false;

                // Check if we've hit any enemies
                if (bird.getRect().intersect(birdEnemy.getRect())){

                    bird.subtractLives(birdEnemy.getDamage());
                    birdEnemyRemove = true;

                    if (bird.getLives() < 0) {
                        /***** Stop the game, save the score, and reset the player and all objects *****/
                        bird.setPlaying(false);
                        saveScore(birdScoreKey, bird.getScore());

                        // Reset
                        bird = new Bird(birdBitmap, birdWidth, birdHeight, birdFrames);
                        birdEnemies = new ArrayList<>();
                        birdExtraLives = new ArrayList<>();
                    }
                }

                birdEnemy.update();

                // Check if any enemies can be removed yet
                if (birdEnemyRemove || birdEnemy.x + birdEnemy.width < 0){
                    birdEnemies.remove(birdEnemy);
                    i--;
                }
            }

            // Check if we can add new enemies
            if (birdEnemies.size() < bird.getScore() / 25 && !thread.markerFrame){
                //int enemyX = WIDTH + (int)(WIDTH * Math.random());
                int enemyX = WIDTH + birdWidth;
                int enemyY = ((int)(Math.random() * HEIGHT));
                // Add constant so that the bird is always slower than the background
                // Prevents birds from looking frozen or like they're going backwards
                int enemySpeed = gameSpeed + ((int)(Math.random() * birdEnemySpeedVariance) + birdEnemySpeedConstant);
                int numBirdEnemiesInRow = 0;
                for (BirdEnemy birdEnemy : birdEnemies){
                    Log.d(TAG, "GameView.update():  enemyY=" + enemyY + ", birdEnemy.y=" + birdEnemy.y);
                    if (birdEnemy.getRect().intersect(new Rect(birdEnemy.x, enemyY, birdEnemy.x + birdWidth, enemyY + birdHeight))){
                        numBirdEnemiesInRow++;
                    }
                }
                Log.d(TAG, "GameView.update():  birdLevel=" + birdLevel);
                Log.d(TAG, "GameView.update():  numBirdEnemiesInRow=" + numBirdEnemiesInRow);

                // Just for a little chaos, 1/100 chance for extra enemies
                boolean addExtraEnemies = ((int) (Math.random() * 100)) == 69;

                // <= so that the game can start
                if (numBirdEnemiesInRow <= birdLevel || addExtraEnemies){
                    Log.d(TAG, "GameView.update():  Adding birdEnemy!");
                    birdEnemies.add(new BirdEnemy(birdEnemyBitmap, birdWidth, birdHeight, birdFrames, enemyX, enemyY, enemySpeed, 1));
                }
            }

            bird.update();
        }
    }

    @Override
    public void draw(Canvas canvas) {

        if (canvas != null) {
            super.draw(canvas);

            final float scaleX = (float) getWidth()/WIDTH;
            final float scaleY = (float) getHeight()/HEIGHT;

            Log.d(TAG, "GameView.draw():  Canvas not null, scaling! scaleX=" + scaleX + ", scaleY=" + scaleY);
            Log.d(TAG, "GameView.draw():  Canvas not null, scaling! getScaleX()=" + getScaleX() + ", getScaleY()=" + getScaleY());

            final int savedState = canvas.save();
            canvas.scale(scaleX, scaleY);

            // Draw all the game's objects
            if (higherQualityEnabled) {
                clouds.draw(canvas);
            }

            background.draw(canvas);

            for (ExtraLife birdExtraLife : birdExtraLives) {
                birdExtraLife.draw(canvas);
            }

            for (BirdEnemy birdEnemy : birdEnemies) {
                birdEnemy.draw(canvas);
            }

            displayScore(canvas);

            bird.draw(canvas);

            // Prevent canvas from infinite scaling
            canvas.restoreToCount(savedState);
        }
    }
}
