import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Iterator;

public class AsteroidsGame extends JPanel implements ActionListener, KeyListener {

    // --- Constants ---
    static final int WIDTH = 800, HEIGHT = 600;
    static final int SHIP_SPEED = 5;
    static final int BULLET_SPEED = 8;
    static final int ROBOT_DROP = 15;

    // --- Inner Classes ---
    class Bullet {
        int x, y;
        Bullet(int x, int y) { this.x = x; this.y = y; }
    }

    class Robot {
        int x, y;
        boolean alive;
        Robot(int x, int y) { this.x = x; this.y = y; this.alive = true; }
    }

    // --- Game state ---
    private Timer timer;
    private int shipX = WIDTH / 2 - 20;
    private boolean moveLeft = false, moveRight = false;
    private int score = 0;
    private boolean gameOver = false;
    private boolean gameWon = false;

    private ArrayList<Bullet> bullets = new ArrayList<>();
    private ArrayList<Robot> robots = new ArrayList<>();

    private int robotDirection = 1;
    private int robotMoveTimer = 0;

    public AsteroidsGame() {
        setPreferredSize(new Dimension(WIDTH, HEIGHT));
        setBackground(Color.BLACK);
        setFocusable(true);
        addKeyListener(this);

        for (int row = 0; row < 3; row++) {
            for (int col = 0; col < 10; col++) {
                robots.add(new Robot(60 + col * 65, 40 + row * 50));
            }
        }

        timer = new Timer(16, this);
        timer.start();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (gameOver || gameWon) return;

        // Move ship
        if (moveLeft && shipX > 0) shipX -= SHIP_SPEED;
        if (moveRight && shipX < WIDTH - 40) shipX += SHIP_SPEED;

        // Move bullets upward
        Iterator<Bullet> bulletIter = bullets.iterator();
        while (bulletIter.hasNext()) {
            Bullet b = bulletIter.next();
            b.y -= BULLET_SPEED;
            if (b.y < 0) bulletIter.remove();
        }

        // Move robots slowly downward and side to side
        robotMoveTimer++;
        if (robotMoveTimer % 60 == 0) {
            boolean hitEdge = false;
            for (Robot r : robots) {
                if (!r.alive) continue;
                r.x += robotDirection * 20;
                if (r.x > WIDTH - 30 || r.x < 10) hitEdge = true;
            }
            if (hitEdge) {
                robotDirection *= -1;
                for (Robot r : robots) {
                    if (!r.alive) continue;
                    r.y += ROBOT_DROP;
                }
            }
        }

        // Bullet vs Robot collision
        bulletIter = bullets.iterator();
        while (bulletIter.hasNext()) {
            Bullet b = bulletIter.next();
            boolean hit = false;
            for (Robot r : robots) {
                if (!r.alive) continue;
                if (b.x >= r.x && b.x <= r.x + 25 && b.y >= r.y && b.y <= r.y + 25) {
                    r.alive = false;
                    score += 10;
                    hit = true;
                    break;
                }
            }
            if (hit) bulletIter.remove();
        }

        // Check win condition — are all robots dead?
        boolean anyAlive = false;
        for (Robot r : robots) {
            if (r.alive) {
                anyAlive = true;
                break;
            }
        }
        if (!anyAlive) {
            gameWon = true;
        }

        // Robot vs Ship collision
        int shipTop = HEIGHT - 70;
        for (Robot r : robots) {
            if (!r.alive) continue;
            if (r.x < shipX + 40 && r.x + 25 > shipX && r.y + 30 >= shipTop) {
                gameOver = true;
            }
        }

        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        if (gameOver) {
            g2.setColor(Color.RED);
            g2.setFont(new Font("Arial", Font.BOLD, 48));
            g2.drawString("GAME OVER", WIDTH / 2 - 140, HEIGHT / 2 - 20);
            g2.setFont(new Font("Arial", Font.PLAIN, 24));
            g2.setColor(Color.WHITE);
            g2.drawString("Final Score: " + score, WIDTH / 2 - 70, HEIGHT / 2 + 30);
            return;
        }

        if (gameWon) {
            g2.setColor(Color.YELLOW);
            g2.setFont(new Font("Arial", Font.BOLD, 48));
            g2.drawString("YOU WIN!", WIDTH / 2 - 120, HEIGHT / 2 - 20);
            g2.setFont(new Font("Arial", Font.PLAIN, 24));
            g2.setColor(Color.WHITE);
            g2.drawString("All robots destroyed!", WIDTH / 2 - 110, HEIGHT / 2 + 30);
            g2.drawString("Final Score: " + score, WIDTH / 2 - 70, HEIGHT / 2 + 65);
            return;
        }

        // Draw score
        g2.setColor(Color.WHITE);
        g2.setFont(new Font("Arial", Font.BOLD, 18));
        g2.drawString("Score: " + score, 10, 25);

        // Draw spaceship
        g2.setColor(Color.CYAN);
        int[] xPoints = {shipX + 20, shipX, shipX + 40};
        int[] yPoints = {HEIGHT - 70, HEIGHT - 40, HEIGHT - 40};
        g2.fillPolygon(xPoints, yPoints, 3);

        // Draw bullets
        g2.setColor(Color.YELLOW);
        for (Bullet b : bullets) {
            g2.fillRect(b.x, b.y, 4, 10);
        }

        // Draw robots
        for (Robot r : robots) {
            if (!r.alive) continue;
            drawRobot(g2, r.x, r.y);
        }
    }

    private void drawRobot(Graphics2D g, int x, int y) {
        g.setColor(Color.GREEN);
        g.fillRect(x, y + 8, 24, 16);
        g.setColor(Color.LIGHT_GRAY);
        g.fillRect(x + 5, y, 14, 10);
        g.setColor(Color.RED);
        g.fillOval(x + 7, y + 2, 4, 4);
        g.fillOval(x + 13, y + 2, 4, 4);
        g.setColor(Color.GREEN);
        g.fillRect(x + 4, y + 24, 6, 6);
        g.fillRect(x + 14, y + 24, 6, 6);
        g.fillRect(x - 4, y + 10, 6, 4);
        g.fillRect(x + 22, y + 10, 6, 4);
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_LEFT) moveLeft = true;
        if (e.getKeyCode() == KeyEvent.VK_RIGHT) moveRight = true;
        if (e.getKeyCode() == KeyEvent.VK_S) {
            bullets.add(new Bullet(shipX + 18, HEIGHT - 72));
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_LEFT) moveLeft = false;
        if (e.getKeyCode() == KeyEvent.VK_RIGHT) moveRight = false;
    }

    @Override public void keyTyped(KeyEvent e) {}

    public static void main(String[] args) {
        JFrame frame = new JFrame("Robot Invasion!");
        AsteroidsGame game = new AsteroidsGame();
        frame.add(game);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}
