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.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;

import java.util.ArrayList;

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

public class ChickenGameView extends GameView {

    private Chicken chicken;
    private Bitmap chickenBitmap;
    private final int chickenWidth = 20;
    private final int chickenHeight = 20;
    private final int chickenFrames = 2;

    private final int lavaHeight = 30;

    private ArrayList<Platform> platforms;
    private Bitmap platformBitmap;
    private final int platformWidth = 32;
    private final int platformHeight = 400;
    private final int platformDefaultY = HEIGHT - lavaHeight;

    private Bitmap backgroundBitmap, lavaBitmap, cloudsBitmap;

    private int chickenGameSpeed = -4;
    private int cloudsSpeed = chickenGameSpeed / 2;
    private int lavaSpeed = chickenGameSpeed - 1;

    private ArrayList<Enemy> enemies;
    private Bitmap enemyBitmap;
    private final int enemyWidth = 32;
    private final int enemyHeight = 32;
    private final int enemyFrames = 1;
    private final int enemySpeed = chickenGameSpeed * 2;

    private String chickenScoreKey;

    private int maxGapSize = 200;

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

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

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        setGameSpeed(chickenGameSpeed);

        // Create global Bitmaps
        if (higherQualityEnabled) {
            backgroundBitmap = BitmapFactory.decodeResource(resources, R.drawable.background_forest_without_clouds);
            lavaBitmap = BitmapFactory.decodeResource(resources, R.drawable.lava);
            cloudsBitmap = BitmapFactory.decodeResource(resources, R.drawable.clouds);
        }
        else{
            backgroundBitmap = BitmapFactory.decodeResource(resources, R.drawable.background_forest_with_lava);
        }
        chickenBitmap = BitmapFactory.decodeResource(resources, R.drawable.chicken);
        platformBitmap = BitmapFactory.decodeResource(resources, R.drawable.normal_platform);
        enemyBitmap = BitmapFactory.decodeResource(resources, R.drawable.enemy);

        // Initialize Background(s)
        background = new GameBackground(backgroundBitmap);
        if (higherQualityEnabled) {
            clouds = new GameBackground(cloudsBitmap);
            lava = new GameBackground(lavaBitmap);
        }

        resetPlatforms();

        enemies = new ArrayList<>();

        chicken = new Chicken(chickenBitmap, chickenWidth, chickenHeight, chickenFrames);

        super.surfaceCreated(holder);
    }

    public void pauseGame() {
        super.pauseGame(chickenScoreKey, chicken.getScore());
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (!chicken.isPlaying()) {
                chicken.setPlaying(true);
            }
            else {
                // Accelerate when moving higher in the air
                /*
                if (chicken.isJumping()) {
                    boost(2, 250);
                }
                // Boost harder on the a jump than a flap
                else{
                    boost(2, 500);
                }
                */
                chicken.jump();
            }
        }

        return super.onTouchEvent(event);
    }

    private void resetPlatforms(){
        platforms = new ArrayList<>();

        // Create initial platform layer
        int platformEndX = 0;
        while (platformEndX < WIDTH){
            Platform platform = new Platform(platformBitmap, platformWidth, platformHeight, platformEndX, platformDefaultY);
            platformEndX = platform.x + platform.width;

            platforms.add(platform);
        }
    }

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

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

        if (!chicken.isPlaying()) {
            textPaint.setColor(Color.parseColor("#330066"));
            canvas.drawText("You are the Purple and White Chicken", 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("Tap the Screen to Jump and Flap", WIDTH / 4, HEIGHT / 4 + textPaint.getTextSize(), textPaint);

            textPaint.setColor(Color.parseColor("#FF0000"));
            canvas.drawText("Don't fall into the lava!", WIDTH / 4, HEIGHT * 3 / 4, textPaint);
        }
    }

    public void endGame(){
        // Stop the game, save, then reset the game
        chicken.setPlaying(false);
        saveScore(chickenScoreKey, chicken.getScore());

        resetPlatforms();
        enemies = new ArrayList<>();
        chicken = new Chicken(chickenBitmap, chickenWidth, chickenHeight, chickenFrames);
    }

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

        if (chicken.isPlaying()) {
            background.update(gameSpeed);
            if (higherQualityEnabled) {
                clouds.update(cloudsSpeed);
                lava.update(lavaSpeed);
            }

            // Remove old platforms
            for (int i = 0; i < platforms.size(); i++) {
                Platform platform = platforms.get(i);

                platform.update(gameSpeed);

                if (platform.x + platform.width < 0) {
                    platforms.remove(platform);
                    i--;
                }
            }

            // Add new platform(s) if the last platform is already being displayed
            // Check where the last platform left off
            boolean createPlatforms = true;
            int lastPlatformEndX = 0;
            for (Platform platform : platforms) {
                if (platform.x > WIDTH) {
                    createPlatforms = false;
                    break;
                } else {
                    lastPlatformEndX = platform.x + platform.width;
                }
            }

            if (createPlatforms && !thread.markerFrame) {
                // Get X
                int newPlatformX;
                // Chance of a gap
                boolean createGap = ((int) (Math.random() * 100) > 69);
                if (createGap) {
                    newPlatformX = lastPlatformEndX + (int) (Math.random() * maxGapSize);
                } else {
                    newPlatformX = lastPlatformEndX;
                }

                // Get Y
                int newPlatformY = platformDefaultY - ((int) (platformHeight * Math.random())) / (chickenHeight * 2);

                // Add the platform
                platforms.add(new Platform(platformBitmap, platformWidth, platformHeight, newPlatformX, newPlatformY));
            }

            // Check if we fell in a hole
            if (chicken.y > HEIGHT) {
                endGame();
            }

            // Refresh enemies array
            boolean enemyOnTop = false;
            for (int i = 0; i < enemies.size() && i >= 0; i++) {
                Enemy enemy = enemies.get(i);

                Log.d(TAG, "ChickenGameView.update():  enemy.getBottomY()=" + enemy.getBottomY());
                // Check if we hit an enemy
                if (chicken.getRect().intersect(enemy.getRect())) {
                    endGame();
                    break;
                }
                // Check if enemy is off the screen
                else if (enemy.getEndX() <= 0) {
                    enemies.remove(enemy);
                    i--;
                }
                // Verify there is still an enemy on top
                else {
                    if (enemy.y < chickenHeight) {
                        enemyOnTop = true;
                    }
                }
            }
            Log.d(TAG, "ChickenGameView.update():  enemyOnTop=" + enemyOnTop);

            // Always prioritize an enemy on the top, else create normal enemies above all the platforms
            if (!thread.markerFrame) {
                if (!enemyOnTop) {
                    int enemyY = (int) (chickenHeight * Math.random());
                    enemies.add(new Enemy(enemyBitmap, enemyWidth, enemyHeight, enemyFrames, WIDTH, enemyY, enemySpeed, 1));
                }
                else if ((chicken.getScore() / 25) > enemies.size()) {
                    int newEnemyHeight = HEIGHT;

                    // Make sure the enemy is always above the platforms
                    for (Platform platform : platforms) {
                        if (platform.y < newEnemyHeight) {
                            newEnemyHeight = platform.y;
                        }
                    }
                    newEnemyHeight -= enemyHeight * 2;
                    newEnemyHeight = (int) (newEnemyHeight * Math.random());
                    enemies.add(new Enemy(enemyBitmap, enemyWidth, enemyHeight, enemyFrames, WIDTH, newEnemyHeight, enemySpeed, 1));
                }
            }

            for (Enemy enemy : enemies){
                enemy.update();
            }

            chicken.update(findPlatformY(chicken, platforms));
        }
    }

    @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);

            if (higherQualityEnabled) {
                lava.draw(canvas);
            }

            for (Platform platform : platforms) {
                platform.draw(canvas);
            }

            for (Enemy enemy : enemies){
                enemy.draw(canvas);
            }

            displayScore(canvas);

            chicken.draw(canvas);

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