import tkinter as tk
from tkinter import font
import math

class Calculator:
    def __init__(self, root):
        self.root = root
        self.root.title("Python 计算器")
        self.root.geometry("400x550")
        self.root.resizable(False, False)
        
        # 设置颜色主题
        self.bg_color = "#2E2E2E"
        self.button_bg = "#424242"
        self.button_fg = "#FFFFFF"
        self.display_bg = "#1A1A1A"
        self.display_fg = "#00FF00"
        self.operator_color = "#FF9500"
        self.special_color = "#A6A6A6"
        
        self.root.configure(bg=self.bg_color)
        
        # 创建自定义字体
        self.display_font = font.Font(family="Consolas", size=24, weight="bold")
        self.button_font = font.Font(family="Arial", size=16, weight="bold")
        
        # 创建显示区域
        self.create_display()
        
        # 创建按钮
        self.create_buttons()
        
        # 初始化变量
        self.current_input = ""
        self.previous_input = ""
        self.operator = ""
        self.result = 0
        self.reset_display = False
        
    def create_display(self):
        # 创建显示框架
        display_frame = tk.Frame(self.root, height=100, bg=self.display_bg)
        display_frame.pack(fill=tk.BOTH, padx=10, pady=(10, 5))
        
        # 主显示区域
        self.display_var = tk.StringVar()
        self.display_var.set("0")
        
        self.display_label = tk.Label(
            display_frame,
            textvariable=self.display_var,
            font=self.display_font,
            bg=self.display_bg,
            fg=self.display_fg,
            anchor="e",
            padx=20
        )
        self.display_label.pack(expand=True, fill=tk.BOTH)
        
        # 历史显示区域
        self.history_var = tk.StringVar()
        self.history_var.set("")
        
        self.history_label = tk.Label(
            display_frame,
            textvariable=self.history_var,
            font=("Arial", 12),
            bg=self.display_bg,
            fg="#888888",
            anchor="e",
            padx=20
        )
        self.history_label.pack(fill=tk.BOTH)
    
    def create_buttons(self):
        # 按钮框架
        button_frame = tk.Frame(self.root, bg=self.bg_color)
        button_frame.pack(expand=True, fill=tk.BOTH, padx=10, pady=5)
        
        # 按钮布局
        buttons = [
            # 第一行
            [
                ("C", self.clear_all, self.special_color),
                ("CE", self.clear_entry, self.special_color),
                ("⌫", self.backspace, self.special_color),
                ("÷", lambda: self.set_operator("/"), self.operator_color)
            ],
            # 第二行
            [
                ("7", lambda: self.add_digit("7"), self.button_bg),
                ("8", lambda: self.add_digit("8"), self.button_bg),
                ("9", lambda: self.add_digit("9"), self.button_bg),
                ("×", lambda: self.set_operator("*"), self.operator_color)
            ],
            # 第三行
            [
                ("4", lambda: self.add_digit("4"), self.button_bg),
                ("5", lambda: self.add_digit("5"), self.button_bg),
                ("6", lambda: self.add_digit("6"), self.button_bg),
                ("-", lambda: self.set_operator("-"), self.operator_color)
            ],
            # 第四行
            [
                ("1", lambda: self.add_digit("1"), self.button_bg),
                ("2", lambda: self.add_digit("2"), self.button_bg),
                ("3", lambda: self.add_digit("3"), self.button_bg),
                ("+", lambda: self.set_operator("+"), self.operator_color)
            ],
            # 第五行
            [
                ("±", self.toggle_sign, self.button_bg),
                ("0", lambda: self.add_digit("0"), self.button_bg),
                (".", self.add_decimal, self.button_bg),
                ("=", self.calculate, self.operator_color)
            ],
            # 科学计算按钮
            [
                ("√", self.square_root, self.button_bg),
                ("x²", self.square, self.button_bg),
                ("1/x", self.reciprocal, self.button_bg),
                ("%", self.percentage, self.button_bg)
            ],
            [
                ("sin", lambda: self.trig_function("sin"), self.button_bg),
                ("cos", lambda: self.trig_function("cos"), self.button_bg),
                ("tan", lambda: self.trig_function("tan"), self.button_bg),
                ("π", self.add_pi, self.button_bg)
            ]
        ]
        
        # 创建按钮
        for row_idx, row in enumerate(buttons):
            button_row = tk.Frame(button_frame, bg=self.bg_color)
            button_row.pack(expand=True, fill=tk.BOTH)
            
            for col_idx, (text, command, color) in enumerate(row):
                btn = tk.Button(
                    button_row,
                    text=text,
                    font=self.button_font,
                    bg=color,
                    fg=self.button_fg,
                    activebackground="#505050",
                    activeforeground=self.button_fg,
                    relief=tk.FLAT,
                    command=command,
                    height=2
                )
                btn.pack(side=tk.LEFT, expand=True, fill=tk.BOTH, padx=2, pady=2)
                
                # 绑定键盘事件
                if text.isdigit() or text in "+-*/=.":
                    self.root.bind_all(text, lambda e, t=text: self.key_press(t))
                elif text == "⌫":
                    self.root.bind_all("<BackSpace>", lambda e: self.backspace())
                elif text == "C":
                    self.root.bind_all("<Escape>", lambda e: self.clear_all())
    
    def key_press(self, key):
        """处理键盘按键"""
        if key.isdigit():
            self.add_digit(key)
        elif key in "+-*/":
            self.set_operator(key)
        elif key == "=" or key == "\r":  # Enter键
            self.calculate()
        elif key == ".":
            self.add_decimal()
    
    def update_display(self):
        """更新显示"""
        if not self.current_input:
            self.display_var.set("0")
        else:
            # 限制显示长度
            if len(self.current_input) > 12:
                self.display_var.set(self.current_input[:12])
            else:
                self.display_var.set(self.current_input)
    
    def add_digit(self, digit):
        """添加数字"""
        if self.reset_display:
            self.current_input = ""
            self.reset_display = False
            
        if self.current_input == "0" or self.current_input == "Error":
            self.current_input = digit
        else:
            self.current_input += digit
        
        self.update_display()
    
    def add_decimal(self):
        """添加小数点"""
        if self.reset_display:
            self.current_input = ""
            self.reset_display = False
            
        if "." not in self.current_input:
            if not self.current_input:
                self.current_input = "0."
            else:
                self.current_input += "."
            self.update_display()
    
    def set_operator(self, op):
        """设置运算符"""
        if self.current_input and not self.reset_display:
            if self.previous_input and self.operator:
                self.calculate()
            
            self.previous_input = self.current_input
            self.operator = op
            
            # 更新历史显示
            if op == "*":
                display_op = "×"
            elif op == "/":
                display_op = "÷"
            else:
                display_op = op
                
            self.history_var.set(f"{self.previous_input} {display_op}")
            self.reset_display = True
    
    def calculate(self):
        """执行计算"""
        if not self.previous_input or not self.operator or not self.current_input:
            return
            
        try:
            num1 = float(self.previous_input)
            num2 = float(self.current_input)
            
            if self.operator == "+":
                result = num1 + num2
            elif self.operator == "-":
                result = num1 - num2
            elif self.operator == "*":
                result = num1 * num2
            elif self.operator == "/":
                if num2 == 0:
                    raise ZeroDivisionError("不能除以零")
                result = num1 / num2
            else:
                return
            
            # 格式化结果
            if result.is_integer():
                result = int(result)
            else:
                # 限制小数位数
                result = round(result, 10)
            
            self.current_input = str(result)
            self.display_var.set(str(result))
            
            # 更新历史显示
            if self.operator == "*":
                display_op = "×"
            elif self.operator == "/":
                display_op = "÷"
            else:
                display_op = self.operator
                
            self.history_var.set(f"{self.previous_input} {display_op} {num2} =")
            
            # 重置状态
            self.previous_input = ""
            self.operator = ""
            self.reset_display = True
            
        except ZeroDivisionError:
            self.display_var.set("Error: 除以零")
            self.current_input = "Error"
            self.reset_display = True
        except Exception as e:
            self.display_var.set("Error")
            self.current_input = "Error"
            self.reset_display = True
    
    def clear_entry(self):
        """清除当前输入"""
        self.current_input = ""
        self.update_display()
    
    def clear_all(self):
        """清除所有"""
        self.current_input = ""
        self.previous_input = ""
        self.operator = ""
        self.history_var.set("")
        self.display_var.set("0")
        self.reset_display = False
    
    def backspace(self):
        """退格"""
        if self.current_input and self.current_input != "Error":
            self.current_input = self.current_input[:-1]
            self.update_display()
    
    def toggle_sign(self):
        """切换正负号"""
        if self.current_input and self.current_input != "0" and self.current_input != "Error":
            if self.current_input[0] == "-":
                self.current_input = self.current_input[1:]
            else:
                self.current_input = "-" + self.current_input
            self.update_display()
    
    def square_root(self):
        """平方根"""
        if self.current_input and self.current_input != "Error":
            try:
                num = float(self.current_input)
                if num < 0:
                    self.display_var.set("Error: 负数")
                    self.current_input = "Error"
                else:
                    result = math.sqrt(num)
                    if result.is_integer():
                        result = int(result)
                    self.current_input = str(result)
                    self.update_display()
                self.reset_display = True
            except:
                self.display_var.set("Error")
                self.current_input = "Error"
                self.reset_display = True
    
    def square(self):
        """平方"""
        if self.current_input and self.current_input != "Error":
            try:
                num = float(self.current_input)
                result = num * num
                if result.is_integer():
                    result = int(result)
                self.current_input = str(result)
                self.update_display()
                self.reset_display = True
            except:
                self.display_var.set("Error")
                self.current_input = "Error"
                self.reset_display = True
    
    def reciprocal(self):
        """倒数"""
        if self.current_input and self.current_input != "Error":
            try:
                num = float(self.current_input)
                if num == 0:
                    self.display_var.set("Error: 除以零")
                    self.current_input = "Error"
                else:
                    result = 1 / num
                    if result.is_integer():
                        result = int(result)
                    self.current_input = str(result)
                    self.update_display()
                self.reset_display = True
            except:
                self.display_var.set("Error")
                self.current_input = "Error"
                self.reset_display = True
    
    def percentage(self):
        """百分比"""
        if self.current_input and self.current_input != "Error":
            try:
                num = float(self.current_input)
                result = num / 100
                self.current_input = str(result)
                self.update_display()
                self.reset_display = True
            except:
                self.display_var.set("Error")
                self.current_input = "Error"
                self.reset_display = True
    
    def trig_function(self, func):
        """三角函数"""
        if self.current_input and self.current_input != "Error":
            try:
                num = float(self.current_input)
                if func == "sin":
                    result = math.sin(math.radians(num))
                elif func == "cos":
                    result = math.cos(math.radians(num))
                elif func == "tan":
                    if math.cos(math.radians(num)) == 0:
                        raise ValueError("无定义")
                    result = math.tan(math.radians(num))
                
                if abs(result) < 1e-10:  # 处理浮点数精度
                    result = 0
                    
                self.current_input = str(round(result, 10))
                self.update_display()
                self.reset_display = True
            except ValueError as e:
                self.display_var.set(f"Error: {str(e)}")
                self.current_input = "Error"
                self.reset_display = True
            except:
                self.display_var.set("Error")
                self.current_input = "Error"
                self.reset_display = True
    
    def add_pi(self):
        """添加π值"""
        if self.reset_display or not self.current_input or self.current_input == "0":
            self.current_input = str(math.pi)
        else:
            self.current_input += str(math.pi)
        self.update_display()

# 主程序
def main():
    root = tk.Tk()
    
    # 设置窗口图标
    try:
        root.iconbitmap("calculator.ico")  # 如果你有图标文件
    except:
        pass
    
    app = Calculator(root)
    root.mainloop()

if __name__ == "__main__":
    main()