package com.weenie.googleballs;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.View;

public class BallsView extends View {
    private PointCollection collection;
    private Paint paint;
    private long lastTime = 0;
    private boolean initialized = false;

    private boolean darkMode = true;
    private boolean showFps = false;
    private int frameCount = 0;
    private long lastFpsTime = 0;
    private float currentFps = 0;

    public BallsView(Context context) {
        super(context);
        paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);
        updateBackgroundColor();
    }

    public void setDarkMode(boolean darkMode) {
        this.darkMode = darkMode;
        updateBackgroundColor();
        invalidate();
    }

    public void setShowFps(boolean showFps) {
        this.showFps = showFps;
        invalidate();
    }

    private void updateBackgroundColor() {
        if (darkMode) {
            setBackgroundColor(Color.parseColor("#1a1a1a"));
        } else {
            setBackgroundColor(Color.WHITE);
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (!initialized) {
            collection = new PointCollection();
            collection.start(w, h);
            initialized = true;
        } else {
            // Recenter
            float oldOffX = (oldw / 2.0f - 180);
            float oldOffY = (oldh / 2.0f - 65);
            float newOffX = (w / 2.0f - 180);
            float newOffY = (h / 2.0f - 65);
            float diffX = newOffX - oldOffX;
            float diffY = newOffY - oldOffY;

            for (Point p : collection.points) {
                p.originalPos.x += diffX;
                p.originalPos.y += diffY;
                // Reset to original position on resize, matching web behavior
                p.curPos.x = p.originalPos.x;
                p.curPos.y = p.originalPos.y;
            }
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (collection == null)
            return;

        long now = System.nanoTime();
        if (lastTime == 0)
            lastTime = now;

        float dt = (now - lastTime) / 1_000_000_000.0f;
        lastTime = now;

        // Cap dt to avoid explosion on lag
        if (dt > 0.1f)
            dt = 0.1f;

        collection.update(dt);
        collection.draw(canvas, paint);

        // FPS Counter logic
        if (showFps) {
            frameCount++;
            if (now - lastFpsTime >= 1_000_000_000) {
                currentFps = frameCount;
                frameCount = 0;
                lastFpsTime = now;
            }
            paint.setColor(darkMode ? Color.WHITE : Color.BLACK);
            paint.setTextSize(40);
            canvas.drawText("FPS: " + (int) currentFps, 20, 120, paint);
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            postInvalidateOnAnimation();
        } else {
            postInvalidate();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (collection == null)
            return false;

        float x = event.getX();
        float y = event.getY();

        collection.mousePos.set(x, y);

        // Keep updating as long as user is interacting, though loop is continuous
        // anyway
        // For web parity, mouse move updates specific target logic.
        // We set mousePos, update(dt) handles the rest.

        // Return true to continue consuming events (movement)
        return true;
    }

    @Override
    public boolean onGenericMotionEvent(MotionEvent event) {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD &&
                (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
            return onTouchEvent(event);
        }
        return super.onGenericMotionEvent(event);
    }
}
