import pygame
import sys
import random
import math
import time
from enum import Enum

# 初始化 Pygame
pygame.init()
pygame.mixer.init()

# 游戏窗口设置
WIDTH, HEIGHT = 1200, 700
GRID_SIZE = 80
GRID_WIDTH = 9
GRID_HEIGHT = 5
GRID_OFFSET_X = 200
GRID_OFFSET_Y = 100
CARD_AREA_HEIGHT = 120
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("真实植物大战僵尸 - 完整版")
clock = pygame.time.Clock()

# 真实配色方案
COLORS = {
    'background': (100, 200, 100),
    'grass_light': (124, 252, 0),
    'grass_dark': (0, 180, 0),
    'grid_line': (0, 100, 0),
    'sun': (255, 200, 0),
    'sunflower': (255, 220, 0),
    'peashooter': (0, 150, 0),
    'repeater': (0, 120, 0),
    'snowpea': (200, 230, 255),
    'wallnut': (139, 90, 43),
    'potato_mine': (139, 69, 19),
    'cherry_bomb': (255, 0, 0),
    'chomper': (0, 100, 0),
    'zombie': (100, 150, 100),
    'conehead': (150, 150, 150),
    'buckethead': (100, 100, 100),
    'newspaper': (240, 240, 240),
    'pole_vaulting': (120, 80, 40),
    'ui_bg': (50, 100, 50),
    'card_bg': (240, 240, 220),
    'card_disabled': (150, 150, 150),
    'text': (255, 255, 255),
    'text_shadow': (0, 0, 0),
    'health_green': (0, 255, 0),
    'health_yellow': (255, 255, 0),
    'health_red': (255, 0, 0),
    'button': (200, 50, 50),
    'button_hover': (255, 100, 100),
    'wave_indicator': (255, 100, 0),
}

# 植物类型枚举
class PlantType(Enum):
    SUNFLOWER = "sunflower"
    PEASHOOTER = "peashooter"
    REPEATER = "repeater"
    SNOWPEA = "snowpea"
    WALLNUT = "wallnut"
    POTATO_MINE = "potato_mine"
    CHERRY_BOMB = "cherry_bomb"
    CHOMPER = "chomper"

# 僵尸类型枚举
class ZombieType(Enum):
    NORMAL = "normal"
    CONEHEAD = "conehead"
    BUCKETHEAD = "buckethead"
    NEWSPAPER = "newspaper"
    POLE_VAULTING = "pole_vaulting"

# 植物卡片类
class PlantCard:
    def __init__(self, plant_type, cost, cooldown, x, y):
        self.plant_type = plant_type
        self.cost = cost
        self.cooldown = cooldown
        self.current_cooldown = 0
        self.rect = pygame.Rect(x, y, 70, 90)
        self.is_selected = False
        self.hover = False
        
    def update(self, sun_count, mouse_pos):
        if self.current_cooldown > 0:
            self.current_cooldown -= 1
            
        self.hover = self.rect.collidepoint(mouse_pos)
        self.clickable = sun_count >= self.cost and self.current_cooldown == 0
        
    def draw(self, surface, font):
        # 卡片背景
        if not self.clickable:
            color = COLORS['card_disabled']
        elif self.hover:
            color = (255, 255, 200)
        elif self.is_selected:
            color = (255, 255, 150)
        else:
            color = COLORS['card_bg']
            
        pygame.draw.rect(surface, color, self.rect, border_radius=8)
        pygame.draw.rect(surface, (100, 100, 100), self.rect, 2, border_radius=8)
        
        # 植物图标
        icon_rect = pygame.Rect(self.rect.x + 10, self.rect.y + 10, 50, 50)
        self._draw_plant_icon(surface, icon_rect)
        
        # 阳光消耗
        cost_text = font.render(str(self.cost), True, COLORS['sun'])
        surface.blit(cost_text, (self.rect.x + 5, self.rect.y + 65))
        
        # 太阳图标
        pygame.draw.circle(surface, COLORS['sun'], 
                         (self.rect.x + 20, self.rect.y + 80), 6)
        
        # 冷却显示
        if self.current_cooldown > 0:
            overlay = pygame.Surface((self.rect.width, self.rect.height), pygame.SRCALPHA)
            overlay.fill((0, 0, 0, 150))
            surface.blit(overlay, self.rect)
            
    def _draw_plant_icon(self, surface, rect):
        center_x = rect.centerx
        center_y = rect.centery
        
        if self.plant_type == PlantType.SUNFLOWER:
            pygame.draw.circle(surface, COLORS['sunflower'], (center_x, center_y), 20)
        elif self.plant_type == PlantType.PEASHOOTER:
            pygame.draw.ellipse(surface, COLORS['peashooter'], rect)
        elif self.plant_type == PlantType.REPEATER:
            pygame.draw.ellipse(surface, COLORS['repeater'], rect)
        elif self.plant_type == PlantType.SNOWPEA:
            pygame.draw.ellipse(surface, COLORS['snowpea'], rect)
        elif self.plant_type == PlantType.WALLNUT:
            pygame.draw.ellipse(surface, COLORS['wallnut'], rect)
        elif self.plant_type == PlantType.POTATO_MINE:
            pygame.draw.ellipse(surface, COLORS['potato_mine'], rect)
        elif self.plant_type == PlantType.CHERRY_BOMB:
            pygame.draw.circle(surface, COLORS['cherry_bomb'], (center_x, center_y), 20)
        elif self.plant_type == PlantType.CHOMPER:
            pygame.draw.ellipse(surface, COLORS['chomper'], rect)

# 植物基类
class Plant:
    def __init__(self, plant_type, grid_x, grid_y):
        self.type = plant_type
        self.grid_x = grid_x
        self.grid_y = grid_y
        self.x = GRID_OFFSET_X + grid_x * GRID_SIZE
        self.y = GRID_OFFSET_Y + grid_y * GRID_SIZE
        self.row = grid_y
        self.health = 100
        self.max_health = 100
        self.attack_cooldown = 0
        self.animation_time = 0
        
        if plant_type == PlantType.SUNFLOWER:
            self.sun_production_time = 300
            self.sun_timer = self.sun_production_time
        elif plant_type == PlantType.PEASHOOTER:
            self.attack_speed = 60
        elif plant_type == PlantType.REPEATER:
            self.attack_speed = 60
        elif plant_type == PlantType.SNOWPEA:
            self.attack_speed = 75
        elif plant_type == PlantType.WALLNUT:
            self.health = 300
            self.max_health = 300
        elif plant_type == PlantType.POTATO_MINE:
            self.arming_time = 300
            self.armed = False
        elif plant_type == PlantType.CHERRY_BOMB:
            self.explosion_timer = 60
        elif plant_type == PlantType.CHOMPER:
            self.digest_timer = 0
            
    def update(self, game):
        self.animation_time += 1
        
        if self.type == PlantType.SUNFLOWER:
            if hasattr(self, 'sun_timer'):
                self.sun_timer -= 1
                if self.sun_timer <= 0:
                    game.suns.append(Sun(self.x + GRID_SIZE//2, self.y))
                    self.sun_timer = self.sun_production_time
                    
        elif self.type in [PlantType.PEASHOOTER, PlantType.REPEATER, PlantType.SNOWPEA]:
            if self.attack_cooldown > 0:
                self.attack_cooldown -= 1
                
            if self.attack_cooldown <= 0:
                for zombie in game.zombies:
                    if zombie.row == self.row and zombie.x > self.x:
                        if self.type == PlantType.PEASHOOTER:
                            game.projectiles.append(Pea(self.x + GRID_SIZE, self.y + GRID_SIZE//2, False))
                        elif self.type == PlantType.REPEATER:
                            game.projectiles.append(Pea(self.x + GRID_SIZE, self.y + GRID_SIZE//2, False))
                        elif self.type == PlantType.SNOWPEA:
                            game.projectiles.append(Pea(self.x + GRID_SIZE, self.y + GRID_SIZE//2, True))
                        self.attack_cooldown = getattr(self, 'attack_speed', 60)
                        break
        
        return False
        
    def draw(self, surface):
        if self.type == PlantType.SUNFLOWER:
            self._draw_sunflower(surface)
        elif self.type == PlantType.PEASHOOTER:
            self._draw_peashooter(surface)
        elif self.type == PlantType.WALLNUT:
            self._draw_wallnut(surface)
        else:
            pygame.draw.rect(surface, (0, 150, 0), 
                           (self.x, self.y, GRID_SIZE, GRID_SIZE))
            
    def _draw_sunflower(self, surface):
        center_x = self.x + GRID_SIZE//2
        center_y = self.y + GRID_SIZE//2
        
        pygame.draw.circle(surface, COLORS['sunflower'], (center_x, center_y), 25)
        
    def _draw_peashooter(self, surface):
        body_rect = pygame.Rect(self.x + 10, self.y + 10, GRID_SIZE - 20, GRID_SIZE - 20)
        pygame.draw.ellipse(surface, COLORS['peashooter'], body_rect)
        
    def _draw_wallnut(self, surface):
        pygame.draw.ellipse(surface, COLORS['wallnut'], 
                          (self.x + 5, self.y + 5, GRID_SIZE - 10, GRID_SIZE - 10))
        
    def get_rect(self):
        return pygame.Rect(self.x, self.y, GRID_SIZE, GRID_SIZE)

# 阳光类
class Sun:
    def __init__(self, x, y, from_plant=False):
        self.x = x
        self.y = y
        self.from_plant = from_plant
        self.size = 20
        self.float_time = 0
        self.lifetime = 600
        
    def update(self):
        self.float_time += 1
        self.lifetime -= 1
        
    def draw(self, surface):
        pygame.draw.circle(surface, COLORS['sun'], (int(self.x), int(self.y)), 15)
        
    def get_rect(self):
        return pygame.Rect(self.x - 25, self.y - 25, 50, 50)
    
    def is_expired(self):
        return self.lifetime <= 0

# 豌豆类
class Pea:
    def __init__(self, x, y, frozen=False):
        self.x = x
        self.y = y
        self.speed = 6
        self.radius = 6
        self.frozen = frozen
        
    def update(self):
        self.x += self.speed
        
    def draw(self, surface):
        if self.frozen:
            color = (150, 200, 255)
        else:
            color = (0, 180, 0)
        pygame.draw.circle(surface, color, (int(self.x), int(self.y)), self.radius)
    
    def get_rect(self):
        return pygame.Rect(self.x - self.radius, self.y - self.radius, 
                          self.radius * 2, self.radius * 2)
        
    def is_off_screen(self):
        return self.x > WIDTH

# 僵尸基类
class Zombie:
    def __init__(self, zombie_type, row):
        self.type = zombie_type
        self.row = row
        self.x = WIDTH
        self.y = GRID_OFFSET_Y + row * GRID_SIZE + GRID_SIZE//2
        self.speed = 0.5
        self.health = 100
        self.max_health = 100
        self.animation_time = 0
        
    def update(self, game):
        self.animation_time += 1
        self.x -= self.speed
        return False
        
    def draw(self, surface):
        # 简单绘制僵尸
        body_rect = pygame.Rect(self.x - 20, self.y - 30, 40, 60)
        
        if self.type == ZombieType.NORMAL:
            color = COLORS['zombie']
        elif self.type == ZombieType.CONEHEAD:
            color = COLORS['conehead']
        elif self.type == ZombieType.BUCKETHEAD:
            color = COLORS['buckethead']
        elif self.type == ZombieType.NEWSPAPER:
            color = COLORS['newspaper']
        else:
            color = COLORS['pole_vaulting']
            
        pygame.draw.rect(surface, color, body_rect, border_radius=5)
        
    def get_rect(self):
        return pygame.Rect(self.x - 20, self.y - 30, 40, 60)
    
    def is_at_house(self):
        return self.x < GRID_OFFSET_X
    
    def is_dead(self):
        return self.health <= 0

# 游戏主类
class PlantsVsZombiesGame:
    def __init__(self):
        self.plants = []
        self.zombies = []
        self.projectiles = []
        self.suns = []
        self.cards = []
        self.selected_plant_type = None
        self.sun_count = 200
        self.wave = 1
        self.zombies_killed = 0
        self.zombies_in_wave = 5
        self.zombies_spawned = 0
        self.spawn_timer = 0
        self.sun_spawn_timer = 0
        self.game_over = False
        self.game_won = False
        self.lives = 5
        
        # 创建植物卡片
        card_types = [
            (PlantType.SUNFLOWER, 50, 300),
            (PlantType.PEASHOOTER, 100, 300),
            (PlantType.REPEATER, 200, 450),
            (PlantType.SNOWPEA, 175, 450),
            (PlantType.WALLNUT, 50, 600),
            (PlantType.POTATO_MINE, 25, 900),
            (PlantType.CHERRY_BOMB, 150, 1200),
            (PlantType.CHOMPER, 150, 600)
        ]
        
        for i, (plant_type, cost, cooldown) in enumerate(card_types[:4]):  # 只显示4种植物
            x = 20 + i * 85
            y = HEIGHT - CARD_AREA_HEIGHT + 15
            self.cards.append(PlantCard(plant_type, cost, cooldown, x, y))
        
        # 字体
        self.font_large = pygame.font.Font(None, 72)
        self.font_medium = pygame.font.Font(None, 48)
        self.font_small = pygame.font.Font(None, 28)
        
        # 生成初始阳光
        for _ in range(3):
            self.suns.append(Sun(
                random.randint(GRID_OFFSET_X, WIDTH - 50),
                random.randint(50, 200),
                from_plant=False
            ))
    
    def get_grid_pos(self, x, y):
        """将屏幕坐标转换为网格坐标"""
        grid_x = (x - GRID_OFFSET_X) // GRID_SIZE
        grid_y = (y - GRID_OFFSET_Y) // GRID_SIZE
        if 0 <= grid_x < GRID_WIDTH and 0 <= grid_y < GRID_HEIGHT:
            return (grid_x, grid_y)
        return None
    
    def is_grid_occupied(self, grid_x, grid_y):
        """检查网格是否被占用"""
        for plant in self.plants:
            if plant.grid_x == grid_x and plant.grid_y == grid_y:
                return True
        return False
    
    def handle_events(self):
        mouse_pos = pygame.mouse.get_pos()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
                
            if event.type == pygame.MOUSEBUTTONDOWN:
                # 收集阳光
                for sun in self.suns[:]:
                    if sun.get_rect().collidepoint(mouse_pos):
                        self.sun_count += 25
                        self.suns.remove(sun)
                
                # 检查卡片点击
                for card in self.cards:
                    if card.rect.collidepoint(mouse_pos) and card.clickable:
                        self.selected_plant_type = card.plant_type
                        for c in self.cards:
                            c.is_selected = False
                        card.is_selected = True
                        break
                
                # 放置植物
                if (self.selected_plant_type and 
                    GRID_OFFSET_X <= mouse_pos[0] < GRID_OFFSET_X + GRID_WIDTH * GRID_SIZE and
                    GRID_OFFSET_Y <= mouse_pos[1] < GRID_OFFSET_Y + GRID_HEIGHT * GRID_SIZE):
                    
                    grid_pos = self.get_grid_pos(mouse_pos[0], mouse_pos[1])
                    if grid_pos and not self.is_grid_occupied(*grid_pos):
                        grid_x, grid_y = grid_pos
                        
                        for card in self.cards:
                            if card.plant_type == self.selected_plant_type and self.sun_count >= card.cost:
                                self.plants.append(Plant(self.selected_plant_type, grid_x, grid_y))
                                self.sun_count -= card.cost
                                card.current_cooldown = card.cooldown
                                card.is_selected = False
                                self.selected_plant_type = None
                                break
                
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()
                if event.key == pygame.K_r:
                    self.__init__()  # 重新开始
                if event.key == pygame.K_SPACE:
                    self.sun_count += 50  # 测试用
    
    def update(self):
        if self.game_over or self.game_won:
            return
        
        mouse_pos = pygame.mouse.get_pos()
        
        # 更新卡片状态
        for card in self.cards:
            card.update(self.sun_count, mouse_pos)
        
        # 更新阳光
        for sun in self.suns[:]:
            sun.update()
            if sun.is_expired():
                self.suns.remove(sun)
        
        # 从天空生成阳光
        self.sun_spawn_timer += 1
        if self.sun_spawn_timer >= 450:
            self.suns.append(Sun(
                random.randint(GRID_OFFSET_X, WIDTH - 50),
                random.randint(50, 200),
                from_plant=False
            ))
            self.sun_spawn_timer = 0
        
        # 更新植物
        for plant in self.plants[:]:
            if plant.update(self):
                self.plants.remove(plant)
        
        # 更新豌豆
        for pea in self.projectiles[:]:
            pea.update()
            
            # 检查击中僵尸
            pea_rect = pea.get_rect()
            for zombie in self.zombies:
                if pea_rect.colliderect(zombie.get_rect()):
                    zombie.health -= 25
                    if pea in self.projectiles:
                        self.projectiles.remove(pea)
                    if zombie.is_dead():
                        self.zombies.remove(zombie)
                        self.zombies_killed += 1
                    break
            
            if pea.is_off_screen():
                self.projectiles.remove(pea)
        
        # 生成僵尸
        if self.zombies_spawned < self.zombies_in_wave:
            self.spawn_timer += 1
            if self.spawn_timer >= 180:
                row = random.randint(0, GRID_HEIGHT - 1)
                zombie_type = random.choice([ZombieType.NORMAL, ZombieType.CONEHEAD])
                self.zombies.append(Zombie(zombie_type, row))
                self.zombies_spawned += 1
                self.spawn_timer = 0
        elif len(self.zombies) == 0:
            self.wave += 1
            if self.wave > 5:
                self.game_won = True
                return
            self.zombies_in_wave = 5 + self.wave
            self.zombies_spawned = 0
        
        # 更新僵尸
        for zombie in self.zombies[:]:
            zombie.update(self)
            
            if zombie.is_at_house():
                self.lives -= 1
                self.zombies.remove(zombie)
                if self.lives <= 0:
                    self.game_over = True
    
    def draw(self):
        # 绘制背景
        screen.fill(COLORS['background'])
        
        # 绘制网格
        for y in range(GRID_HEIGHT):
            for x in range(GRID_WIDTH):
                rect = pygame.Rect(
                    GRID_OFFSET_X + x * GRID_SIZE,
                    GRID_OFFSET_Y + y * GRID_SIZE,
                    GRID_SIZE, GRID_SIZE
                )
                if (x + y) % 2 == 0:
                    pygame.draw.rect(screen, COLORS['grass_light'], rect)
                else:
                    pygame.draw.rect(screen, COLORS['grass_dark'], rect)
                pygame.draw.rect(screen, COLORS['grid_line'], rect, 1)
        
        # 绘制UI背景
        pygame.draw.rect(screen, COLORS['ui_bg'], (0, 0, WIDTH, 80))
        pygame.draw.rect(screen, (139, 90, 43), (0, HEIGHT - CARD_AREA_HEIGHT, WIDTH, CARD_AREA_HEIGHT))
        
        # 绘制游戏元素
        for pea in self.projectiles:
            pea.draw(screen)
            
        for plant in self.plants:
            plant.draw(screen)
            
        for zombie in self.zombies:
            zombie.draw(screen)
            
        for sun in self.suns:
            sun.draw(screen)
        
        # 绘制卡片
        for card in self.cards:
            card.draw(screen, self.font_small)
        
        # 绘制UI信息
        # 阳光
        sun_text = self.font_medium.render(f"阳光: {self.sun_count}", True, COLORS['text'])
        screen.blit(sun_text, (20, 20))
        
        # 波数
        wave_text = self.font_small.render(f"波数: {self.wave}/5", True, COLORS['text'])
        screen.blit(wave_text, (200, 25))
        
        # 生命
        life_text = self.font_small.render(f"生命: {self.lives}", True, COLORS['text'])
        screen.blit(life_text, (350, 25))
        
        # 击杀
        kill_text = self.font_small.render(f"击杀: {self.zombies_killed}", True, COLORS['text'])
        screen.blit(kill_text, (500, 25))
        
        # 标题
        title_text = self.font_large.render("植物大战僵尸", True, (255, 255, 224))
        screen.blit(title_text, (WIDTH//2 - title_text.get_width()//2, 10))
        
        # 控制说明
        controls = [
            "点击卡片选择植物 → 点击草地放置",
            "点击太阳收集阳光",
            "空格键: 获得50阳光(测试用)",
            "R键: 重新开始",
            "ESC键: 退出"
        ]
        
        for i, text in enumerate(controls):
            control_text = self.font_small.render(text, True, (255, 255, 224))
            screen.blit(control_text, (WIDTH//2 - 250, 50 + i * 25))
        
        # 游戏结束画面
        if self.game_over:
            overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
            overlay.fill((0, 0, 0, 180))
            screen.blit(overlay, (0, 0))
            
            game_over_text = self.font_large.render("游戏结束!", True, (255, 50, 50))
            score_text = self.font_medium.render(f"最终波数: {self.wave}", True, (255, 255, 255))
            restart_text = self.font_small.render("按 R 键重新开始", True, (200, 200, 200))
            
            screen.blit(game_over_text, (WIDTH//2 - game_over_text.get_width()//2, HEIGHT//2 - 100))
            screen.blit(score_text, (WIDTH//2 - score_text.get_width()//2, HEIGHT//2 - 30))
            screen.blit(restart_text, (WIDTH//2 - restart_text.get_width()//2, HEIGHT//2 + 40))
            
        # 游戏胜利画面
        if self.game_won:
            overlay = pygame.Surface((WIDTH, HEIGHT), pygame.SRCALPHA)
            overlay.fill((0, 0, 0, 180))
            screen.blit(overlay, (0, 0))
            
            win_text = self.font_large.render("恭喜通关!", True, (50, 205, 50))
            score_text = self.font_medium.render(f"最终波数: {self.wave}", True, (255, 255, 255))
            restart_text = self.font_small.render("按 R 键重新开始", True, (200, 200, 200))
            
            screen.blit(win_text, (WIDTH//2 - win_text.get_width()//2, HEIGHT//2 - 100))
            screen.blit(score_text, (WIDTH//2 - score_text.get_width()//2, HEIGHT//2 - 30))
            screen.blit(restart_text, (WIDTH//2 - restart_text.get_width()//2, HEIGHT//2 + 40))

# 主游戏循环
def main():
    game = PlantsVsZombiesGame()
    
    while True:
        game.handle_events()
        game.update()
        game.draw()
        pygame.display.flip()
        clock.tick(60)

if __name__ == "__main__":
    print("="*60)
    print("🌻 真实植物大战僵尸 - 简化版")
    print("="*60)
    print("游戏说明:")
    print("- 种植植物防御僵尸入侵")
    print("- 收集阳光购买植物")
    print("- 保护左侧的房子")
    print("- 抵御5波僵尸攻击获胜!")
    print("="*60)
    print("植物类型:")
    print("🌻 向日葵: 产生阳光(50阳光)")
    print("🌱 豌豆射手: 发射豌豆攻击(100阳光)")
    print("🌱 双发射手: 一次发射两颗豌豆(200阳光)")
    print("❄️ 寒冰射手: 发射冰冻豌豆(175阳光)")
    print("🥜 坚果墙: 高生命值防御(50阳光)")
    print("="*60)
    print("控制说明:")
    print("- 鼠标点击: 选择/放置植物，收集阳光")
    print("- 空格键: 获得50阳光(测试用)")
    print("- R键: 重新开始游戏")
    print("- ESC键: 退出游戏")
    print("="*60)
    print("游戏启动中...")
    
    try:
        main()
    except pygame.error as e:
        print(f"错误: {e}")
        print("请确保已正确安装 pygame 库")
        print("运行: pip install pygame")