import socket
import threading
import json
import tkinter as tk
from tkinter import messagebox
import math
import sys

class TankGameClient:
    def __init__(self, host='127.0.0.1', port=12345):
        self.host = host
        self.port = port
        self.socket = None
        self.player_id = None
        self.username = None
        self.game_state = None
        self.running = False
        self.keys_pressed = set()
        
        # GUI
        self.root = tk.Tk()
        self.root.title("坦克大战 - 联网对战")
        self.root.geometry("900x650")
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
        
        self.setup_gui()
        self.show_connect_dialog()
    
    def setup_gui(self):
        """设置GUI"""
        # 主框架
        self.main_frame = tk.Frame(self.root)
        self.main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 游戏画布
        self.canvas = tk.Canvas(
            self.main_frame,
            width=800,
            height=600,
            bg='black',
            highlightthickness=2,
            highlightbackground='#2c3e50'
        )
        self.canvas.pack(side=tk.LEFT, padx=5, pady=5)
        
        # 右侧信息面板
        self.info_frame = tk.Frame(self.main_frame, width=150)
        self.info_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=5, pady=5)
        
        # 玩家信息
        self.info_label = tk.Label(self.info_frame, text="游戏信息", font=('Arial', 12, 'bold'))
        self.info_label.pack(pady=10)
        
        self.score_frame = tk.Frame(self.info_frame)
        self.score_frame.pack(fill=tk.BOTH, expand=True)
        
        self.score_labels = {}
        
        # 聊天区域
        self.chat_frame = tk.Frame(self.info_frame)
        self.chat_frame.pack(fill=tk.BOTH, expand=True, pady=10)
        
        tk.Label(self.chat_frame, text="聊天", font=('Arial', 10, 'bold')).pack()
        
        self.chat_display = tk.Text(
            self.chat_frame,
            height=8,
            width=20,
            state=tk.DISABLED,
            bg='#ecf0f1'
        )
        self.chat_display.pack(fill=tk.BOTH, expand=True)
        
        self.chat_entry = tk.Entry(self.chat_frame)
        self.chat_entry.pack(fill=tk.X)
        self.chat_entry.bind('<Return>', self.send_chat)
        
        # 控制提示
        control_text = """
        控制:
        ↑ ↓ ← → 移动
        空格键 射击
        Enter 发送消息
        """
        tk.Label(self.info_frame, text=control_text, justify=tk.LEFT, font=('Arial', 9)).pack(pady=10)
        
        # 绑定键盘事件
        self.root.bind('<KeyPress>', self.on_key_press)
        self.root.bind('<KeyRelease>', self.on_key_release)
        self.root.focus_set()
    
    def show_connect_dialog(self):
        """连接对话框"""
        dialog = tk.Toplevel(self.root)
        dialog.title("连接服务器")
        dialog.geometry("400x250")
        dialog.transient(self.root)
        dialog.grab_set()
        
        tk.Label(dialog, text="坦克大战 - 联网对战", font=('Arial', 16, 'bold')).pack(pady=10)
        
        form = tk.Frame(dialog)
        form.pack(pady=10)
        
        tk.Label(form, text="服务器地址:").grid(row=0, column=0, sticky=tk.W, pady=5)
        host_entry = tk.Entry(form, width=30)
        host_entry.insert(0, '127.0.0.1')
        host_entry.grid(row=0, column=1, pady=5)
        
        tk.Label(form, text="端口:").grid(row=1, column=0, sticky=tk.W, pady=5)
        port_entry = tk.Entry(form, width=30)
        port_entry.insert(0, '12345')
        port_entry.grid(row=1, column=1, pady=5)
        
        tk.Label(form, text="用户名:").grid(row=2, column=0, sticky=tk.W, pady=5)
        username_entry = tk.Entry(form, width=30)
        username_entry.grid(row=2, column=1, pady=5)
        username_entry.focus()
        
        def connect():
            host = host_entry.get().strip()
            port = int(port_entry.get().strip())
            username = username_entry.get().strip()
            
            if not username:
                messagebox.showerror("错误", "请输入用户名")
                return
            
            self.host = host
            self.port = port
            self.username = username
            
            if self.connect_to_server():
                dialog.destroy()
                self.root.title(f"坦克大战 - {self.username}")
        
        tk.Button(
            dialog,
            text="连接",
            command=connect,
            bg='#3498db',
            fg='white',
            width=20
        ).pack(pady=20)
        
        dialog.bind('<Return>', lambda e: connect())
    
    def connect_to_server(self):
        """连接服务器"""
        try:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.connect((self.host, self.port))
            
            # 发送用户名
            self.socket.send(json.dumps({
                'username': self.username
            }).encode('utf-8'))
            
            # 启动接收线程
            self.running = True
            receive_thread = threading.Thread(target=self.receive_messages, daemon=True)
            receive_thread.start()
            
            # 启动发送线程
            send_thread = threading.Thread(target=self.send_loop, daemon=True)
            send_thread.start()
            
            return True
            
        except Exception as e:
            messagebox.showerror("错误", f"连接失败: {e}")
            return False
    
    def receive_messages(self):
        """接收消息"""
        while self.running:
            try:
                data = self.socket.recv(4096).decode('utf-8')
                if not data:
                    break
                
                message = json.loads(data)
                self.handle_message(message)
                
            except json.JSONDecodeError:
                continue
            except:
                break
        
        if self.running:
            self.root.after(0, self.handle_disconnect)
    
    def handle_message(self, message):
        """处理消息"""
        msg_type = message.get('type')
        
        if msg_type == 'init':
            # 初始化
            self.player_id = message['player_id']
            self.game_state = message['game_state']
            self.root.after(0, self.update_display)
            
        elif msg_type == 'game_state':
            # 更新游戏状态
            self.game_state = message['state']
            self.root.after(0, self.update_display)
            
        elif msg_type == 'system':
            # 系统消息
            self.add_chat_message(f"[系统] {message['message']}")
            
        elif msg_type == 'chat':
            # 聊天消息
            self.add_chat_message(f"{message['username']}: {message['message']}")
            
        elif msg_type == 'error':
            messagebox.showerror("错误", message['message'])
    
    def send_loop(self):
        """发送循环 - 处理玩家输入"""
        while self.running:
            try:
                if self.player_id:
                    # 处理移动
                    dx = 0
                    dy = 0
                    if 'Up' in self.keys_pressed:
                        dy = -1
                    if 'Down' in self.keys_pressed:
                        dy = 1
                    if 'Left' in self.keys_pressed:
                        dx = -1
                    if 'Right' in self.keys_pressed:
                        dx = 1
                    
                    # 发送移动消息
                    if dx != 0 or dy != 0:
                        self.send_json({
                            'type': 'move',
                            'dx': dx,
                            'dy': dy
                        })
                    
                    # 处理射击
                    if 'space' in self.keys_pressed:
                        self.send_json({
                            'type': 'shoot'
                        })
                        # 防止连续射击
                        self.keys_pressed.discard('space')
                
                time.sleep(1/30)  # 30 FPS
                
            except:
                break
    
    def send_json(self, data):
        """发送JSON数据"""
        try:
            self.socket.send(json.dumps(data).encode('utf-8'))
        except:
            pass
    
    def send_chat(self, event=None):
        """发送聊天消息"""
        message = self.chat_entry.get().strip()
        if message:
            self.send_json({
                'type': 'chat',
                'message': message
            })
            self.chat_entry.delete(0, tk.END)
    
    def add_chat_message(self, message):
        """添加聊天消息"""
        self.chat_display.config(state=tk.NORMAL)
        self.chat_display.insert(tk.END, message + '\n')
        self.chat_display.see(tk.END)
        self.chat_display.config(state=tk.DISABLED)
    
    def update_display(self):
        """更新游戏显示"""
        self.canvas.delete('all')
        
        if not self.game_state:
            return
        
        # 绘制网格
        for i in range(0, 800, 40):
            self.canvas.create_line(i, 0, i, 600, fill='#1a1a1a')
        for i in range(0, 600, 40):
            self.canvas.create_line(0, i, 800, i, fill='#1a1a1a')
        
        # 绘制玩家
        for player_id, player in self.game_state['players'].items():
            color = '#00ff00' if player_id == self.player_id else '#ff0000'
            if player['alive']:
                self.draw_tank(player['x'], player['y'], player['angle'], color)
            else:
                # 死亡标记
                self.canvas.create_text(
                    player['x'], player['y'],
                    text='💀',
                    font=('Arial', 30),
                    fill='red'
                )
        
        # 绘制子弹
        for bullet in self.game_state['bullets']:
            x = bullet['x']
            y = bullet['y']
            self.canvas.create_oval(
                x-4, y-4, x+4, y+4,
                fill='yellow',
                outline='orange'
            )
        
        # 更新分数
        self.update_score()
    
    def draw_tank(self, x, y, angle, color):
        """绘制坦克"""
        # 坦克身体
        self.canvas.create_rectangle(
            x-15, y-15, x+15, y+15,
            fill=color,
            outline='white'
        )
        
        # 炮塔
        self.canvas.create_oval(
            x-10, y-10, x+10, y+10,
            fill=color,
            outline='white'
        )
        
        # 炮管
        length = 25
        end_x = x + math.cos(angle) * length
        end_y = y + math.sin(angle) * length
        self.canvas.create_line(
            x, y, end_x, end_y,
            fill='white',
            width=4
        )
        
        # 生命值
        health = 3
        for i in range(health):
            self.canvas.create_rectangle(
                x-15 + i*10, y-25,
                x-5 + i*10, y-20,
                fill='green' if i < health else 'gray'
            )
    
    def update_score(self):
        """更新分数显示"""
        # 清除旧分数
        for widget in self.score_frame.winfo_children():
            widget.destroy()
        
        if self.game_state and 'score' in self.game_state:
            for username, score in self.game_state['score'].items():
                label = tk.Label(
                    self.score_frame,
                    text=f"{username}: {score}",
                    font=('Arial', 10)
                )
                label.pack()
    
    def on_key_press(self, event):
        """键盘按下"""
        key = event.keysym.lower()
        if key == 'space':
            self.keys_pressed.add('space')
        else:
            self.keys_pressed.add(event.keysym)
    
    def on_key_release(self, event):
        """键盘释放"""
        key = event.keysym.lower()
        if key == 'space':
            self.keys_pressed.discard('space')
        else:
            self.keys_pressed.discard(event.keysym)
    
    def handle_disconnect(self):
        """处理断开连接"""
        self.running = False
        messagebox.showwarning("断开连接", "与服务器断开连接")
        self.root.destroy()
    
    def on_closing(self):
        """关闭窗口"""
        self.running = False
        if self.socket:
            try:
                self.socket.close()
            except:
                pass
        self.root.destroy()
        sys.exit(0)
    
    def run(self):
        """运行客户端"""
        self.root.mainloop()

if __name__ == "__main__":
    client = TankGameClient()
    client.run()