package cisc181.simpleanimate;

/*

SimpleAnimate app -- animated drawing in a separate thread

Christopher Rasmussen
copyright 2017, University of Delaware

*/

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.LightingColorFilter;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.lang.Override;

// note that we are not implementing the SurfaceHolder.Callback interface at this level anymore

public class MyAnimatedSurfaceView extends SurfaceView {

    private MyThread myThread;

    Paint mPaint, mPaintHit, mPaintMiss;
    Bitmap bmap;

    // object position, velocity

    int xPos = 0;
    int yPos = 0;
    double xDelta = 5;
    double yDelta = 5;
    double xAccel = 1.1;
    double yAccel = 1.1;

    // object orientation

    int angleDegs = 0;
    int angleDegsDelta = 5;

    // object scale

    float scaleFactor = 3.0f;

    // touch activity

    boolean touchDown = false;
    boolean touchStarted = false;
    boolean touchHit = false;
    float touchX, touchY;

    // constructor

    public MyAnimatedSurfaceView(Context context, AttributeSet attrs) {

        super(context, attrs);

        myThread = new MyThread(this);

        mPaint = new Paint();
        mPaint.setStrokeWidth(5);

        mPaintHit = new Paint();
        ColorFilter redFilter = new LightingColorFilter(Color.RED, 0);
        mPaintHit.setColorFilter(redFilter);

        mPaintMiss = new Paint();
        ColorFilter blueFilter = new LightingColorFilter(Color.BLUE, 0);
        mPaintMiss.setColorFilter(blueFilter);

        bmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);

        SurfaceHolder holder = getHolder();

        // implement SurfaceHolder.Callback interface with anonymous inner class

        holder.addCallback(new SurfaceHolder.Callback() {

            // start draw thread

            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                myThread.setRunning(true);
                myThread.start();
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

            }

            // stop draw thread

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
                boolean retry = true;
                myThread.setRunning(false);
                while (retry) {
                    try {
                        myThread.join();
                        retry = false;
                    }
                    catch (InterruptedException e) { }
                }
            }
        });

    }

    // do drawing on current canvas

    public void myDraw(Canvas canvas) {

        // clear background

        canvas.drawColor(Color.BLACK);

        // if touch, draw line joining to sprite location

        if (touchDown) {
            mPaint.setColor(Color.RED);
            canvas.drawLine(xPos + bmap.getWidth() / 2, yPos + bmap.getHeight() / 2, touchX, touchY, mPaint);
        }

        // change direction because of hit?

        if (touchStarted && touchHit) {
            xDelta *= xAccel;
            yDelta *= yAccel;
        }

        // draw sprite

        canvas.save();
        canvas.rotate(angleDegs, xPos + bmap.getWidth() / 2, yPos + bmap.getHeight() / 2);

        // player took "shot"

        if (touchDown) {

            // hit -- "blow up" sprite and tint it red

            if (touchHit) {
                canvas.scale(scaleFactor, scaleFactor, xPos + bmap.getWidth() / 2, yPos + bmap.getHeight() / 2);
                canvas.drawBitmap(bmap, xPos, yPos, mPaintHit);
            }

            // miss -- tint blue

            else
                canvas.drawBitmap(bmap, xPos, yPos, mPaintMiss);

        }

        // no shot -- draw normally

        else
            canvas.drawBitmap(bmap, xPos, yPos, mPaint);

        canvas.restore();

        // check for "bounce" off all 4 sides

        if ((xDelta > 0 && xPos + bmap.getWidth() >= getWidth()) || (xDelta < 0 && xPos < 0)) {
            xDelta = -xDelta;
        }
        else if ((yDelta > 0 && yPos + bmap.getHeight() >= getHeight()) || (yDelta < 0 && yPos < 0)) {
            yDelta = -yDelta;
        }

        // actually update position, orientation

        xPos += xDelta;
        yPos += yDelta;

        angleDegs += angleDegsDelta;

    }

    // respond to the SurfaceView being clicked/dragged

    public boolean onTouchEvent(MotionEvent e) {

        // determine whether touch is still active or has just ended

        if (e.getAction() == MotionEvent.ACTION_DOWN) {
            touchDown = true;        // finger down
            touchStarted = true;     // finger JUST went down
            touchX = e.getX();       // where finger is
            touchY = e.getY();

            // is touch close enough to object to count as hit?

            if (touchX >= xPos && touchX < xPos + bmap.getWidth() && touchY >= yPos && touchY < yPos + bmap.getHeight()) {
                touchHit = true;
            }
            else {
                touchHit = false;
            }
        }

        // finger down and dragging

        else if (e.getAction() == MotionEvent.ACTION_MOVE) {
            touchStarted = false;    // finger has been down for awhile now
            touchX = e.getX();
            touchY = e.getY();
        }

        // finger is up after being down

        else if (e.getAction() == MotionEvent.ACTION_UP) {
            touchDown = false;       // finger up
            touchStarted = false;    // so a touch cannot have just been started
        }

        // unrecognized motion event

        else {
            return false;
        }

        // do NOT force a redraw -- just wait for MyThread's next draw call

        return true;
    }
}