import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.Iterator;
import java.util.List;

import javax.swing.JPanel;

@SuppressWarnings("serial")
public class GamePanel extends JPanel {
    public GamePanel() {
        // 创建数字的图像
        BufferedImage numbersImage = Config.getInstance().getNumbersImage();
        if (numbersImage != null) {
            numbers = new Image[10];
            numberWidth = Config.getInstance().getNumberWidth();
            numberHeight = Config.getInstance().getNumberHeight();
            for (int i = 0; i < 10; ++i) {
                numbers[i] = numbersImage.getSubimage(i * numberWidth, 0, numberWidth, numberHeight);
            }
        }
    }

    public void display(Shape currentShape, List<Shape> nextShapes, Ground ground) {
        this.currentShape = currentShape;
        this.nextShapes = nextShapes;
        this.ground = ground;

        repaint();
    }

    public void setScore(int score) {
        this.score = score;
    }
    
    public void setGameOver(boolean gameOver) {
        this.gameOver = gameOver;
    }

    @Override
    protected void paintComponent(Graphics g) {
        // 使用JPanel的双缓冲功能，否则得自己使用离屏环境实现双缓冲
        super.paintComponent(g);

        // 绘制背景
        drawBackgroundImage(g);

        // Draw ground.
        drawGround(g);

        // Draw current shape.
        drawCurrentShape(g);

        // Draw ground grid
        // drawGrid(g);

        // Draw next shape
        drawNextShapes(g);


        if (gameOver) {
            drawGameOver(g);
        }
        
        // Draw score
        drawScore(g);
    }
    
    protected void drawBackgroundImage(Graphics g) {
        if (Config.getInstance().isBackgroundDrawn()) {
            Image img = Config.getInstance().getBackgroundImage();
            if (img == null) { return ; }
            int w = img.getWidth(null);
            int h = img.getHeight(null);
            g.drawImage(img, 0, 0, w, h, null);
        }
    }

    // 绘制当前正下落的方块
    protected void drawCurrentShape(Graphics g) {
        if (currentShape == null) { return ; }
        
        int shapeX = currentShape.getX();
        int shapeY = currentShape.getY();

        int w = Config.getInstance().getCellWidth();
        int h = Config.getInstance().getCellHeight();

        for (int x = 0; x < currentShape.getColumnCount(); ++x) {
            for (int y = 0; y < currentShape.getRowCount(); ++y) {
                if (currentShape.getCellValue(x, y) == 1) {
                    g.drawImage(currentShape.getImage(), (shapeX + x) * w, (shapeY + y) * h, w, h, null);
                }
            }
        }
    }

    // 绘制下一个方块，如果使用队列存储，还可以预先绘制任意个方块
    protected void drawNextShapes(Graphics g) {
        if (nextShapes == null || nextShapes.size() == 0) { return ; }
        
        int sw = 10;
        int sh = 10;
        int rowCount = nextShapes.get(0).getRowCount();
        int colCount = nextShapes.get(0).getColumnCount();
        int shapeHeight = rowCount * sh;
        int offsetY = shapeHeight * (nextShapes.size() -1 );
        
        Iterator<Shape> iter = nextShapes.iterator();
        while (iter.hasNext()) {
            Shape shape = iter.next();
            
            for (int x = 0; x < colCount; ++x) {
                for (int y = 0; y < rowCount; ++y) {
                    if (shape.getCellValue(x, y) == 1) {
                        g.drawImage(shape.getImage(), x * sw, y * sh + offsetY, sw, sh, null);
                    }
                }
            }
            
            offsetY -= shapeHeight;
        }
    }

    // 绘制底部不能动的方块: 战场，地面
    protected void drawGround(Graphics g) {
        if (ground == null) { return ; }
        
        int w = Config.getInstance().getCellWidth();
        int h = Config.getInstance().getCellHeight();

        int rowCount = ground.getRowCount();
        int colCount = ground.getColumnCount();
        

        for (int x = 0; x < colCount; ++x) {
            for (int y = 0; y < rowCount; ++y) {
                if (ground.getCellValue(x, y) == 1) {
                    // 让Ground中的方块不透明，还有意思些
                    g.setColor(ground.getCellColor(x, y));
                    g.fillRect(x * w +1 , y * h + 1, w - 2, h - 2);

                    g.drawImage(ground.getCellImage(x, y), x * w, y * h, w, h, null);
                }
            }
        }
    }

    // 绘制网格线，其实没多大必要
    protected void drawGrid(Graphics g) {
        int w = Config.getInstance().getCellWidth();
        int h = Config.getInstance().getCellHeight();

        g.setColor(Config.getInstance().getGridColor());
        int rowCount = Config.getInstance().getGroundRowCount();
        int colCount = Config.getInstance().getGroundColumnCount();

        // Draw horinzontal line
        for (int i = 0; i <= rowCount; ++i) {
            g.drawLine(0, i * h, colCount * w, i * h);
        }

        // Draw vertical line
        for (int i = 0; i <= colCount; ++i) {
            g.drawLine(i * w, 0, i * w, rowCount * h);
        }
    }

    // 在右上角绘制得分
    protected void drawScore(Graphics g) {
        if (numbers == null) { return; }
        
        int n = score;
        int startX = getWidth() - 20;
        do {
            g.drawImage(numbers[n % 10], startX, 10, numberWidth, numberHeight, null);
            startX -= numberWidth;
            n /= 10;
        } while (n != 0);
    }

    private void drawGameOver(Graphics g) {
        Image gameOver = Config.getInstance().getGameOverImage();
        if (gameOver == null) { return ; }
        
        int w = gameOver.getWidth(null);
        int h = gameOver.getHeight(null);

        g.drawImage(gameOver, (getWidth() - w) / 2, 20, w, h, null);
    }

    private Shape currentShape;
    private List<Shape> nextShapes;
    private Ground ground;
    private int score;
    private boolean gameOver = false;
    private Image[] numbers;
    private int numberWidth;
    private int numberHeight;
}
