import pygame
import sys
import math

# 初始化 Pygame
pygame.init()

# 颜色定义
COLORS = {
    'background': (25, 25, 35),      # 深色背景
    'display': (15, 15, 25),         # 显示屏背景
    'display_text': (220, 220, 255), # 显示屏文字
    'button_normal': (40, 40, 55),   # 普通按钮
    'button_hover': (60, 60, 75),    # 按钮悬停
    'button_press': (80, 80, 95),    # 按钮按下
    'operator': (70, 130, 180),      # 运算符按钮
    'operator_hover': (90, 150, 200),
    'equals': (0, 150, 100),         # 等号按钮
    'equals_hover': (0, 180, 120),
    'clear': (180, 70, 70),          # 清除按钮
    'clear_hover': (200, 90, 90),
    'scientific': (100, 70, 140),    # 科学函数按钮
    'scientific_hover': (120, 90, 160),
    'text': (240, 240, 240),         # 按钮文字
    'shadow': (10, 10, 15),          # 阴影
}

# 窗口设置
WIDTH, HEIGHT = 500, 700
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("高级科学计算器")
clock = pygame.time.Clock()

# 字体
try:
    display_font = pygame.font.Font(None, 64)
    button_font = pygame.font.Font(None, 36)
    small_font = pygame.font.Font(None, 28)
except:
    # 如果字体加载失败，使用默认字体
    display_font = pygame.font.SysFont('arial', 64)
    button_font = pygame.font.SysFont('arial', 36)
    small_font = pygame.font.SysFont('arial', 28)

# 计算器状态
class Calculator:
    def __init__(self):
        self.reset()
    
    def reset(self):
        self.current_input = "0"
        self.previous_input = ""
        self.operator = None
        self.waiting_for_operand = False
        self.memory = 0
        self.show_scientific = False
        self.error = False
    
    def input_digit(self, digit):
        if self.error:
            self.current_input = digit
            self.error = False
        elif self.current_input == "0" or self.waiting_for_operand:
            self.current_input = digit
            self.waiting_for_operand = False
        else:
            self.current_input += digit
    
    def input_decimal(self):
        if self.error:
            self.current_input = "0."
            self.error = False
        elif "." not in self.current_input:
            if self.waiting_for_operand:
                self.current_input = "0."
                self.waiting_for_operand = False
            else:
                self.current_input += "."
    
    def toggle_sign(self):
        if self.current_input and self.current_input != "0":
            if self.current_input[0] == "-":
                self.current_input = self.current_input[1:]
            else:
                self.current_input = "-" + self.current_input
    
    def input_operator(self, op):
        if self.error:
            return
            
        if self.operator and not self.waiting_for_operand:
            self.calculate()
        
        self.operator = op
        self.previous_input = self.current_input
        self.waiting_for_operand = True
    
    def calculate(self):
        if self.error or not self.operator:
            return
        
        try:
            a = float(self.previous_input)
            b = float(self.current_input)
            
            if self.operator == "+":
                result = a + b
            elif self.operator == "-":
                result = a - b
            elif self.operator == "×":
                result = a * b
            elif self.operator == "÷":
                if b == 0:
                    self.current_input = "错误：除零"
                    self.error = True
                    return
                result = a / b
            elif self.operator == "^":
                result = a ** b
            elif self.operator == "%":
                result = a % b
            
            # 处理结果
            if result.is_integer():
                self.current_input = str(int(result))
            else:
                # 限制小数位数
                self.current_input = f"{result:.10f}".rstrip('0').rstrip('.')
            
            self.operator = None
            self.waiting_for_operand = True
            
        except Exception as e:
            self.current_input = "错误"
            self.error = True
    
    def scientific_function(self, func):
        if self.error:
            return
            
        try:
            x = float(self.current_input)
            result = 0
            
            if func == "sin":
                result = math.sin(math.radians(x))
            elif func == "cos":
                result = math.cos(math.radians(x))
            elif func == "tan":
                if x % 180 == 90:  # tan(90°) 未定义
                    self.current_input = "错误"
                    self.error = True
                    return
                result = math.tan(math.radians(x))
            elif func == "log":
                if x <= 0:
                    self.current_input = "错误"
                    self.error = True
                    return
                result = math.log10(x)
            elif func == "ln":
                if x <= 0:
                    self.current_input = "错误"
                    self.error = True
                    return
                result = math.log(x)
            elif func == "√":
                if x < 0:
                    self.current_input = "错误"
                    self.error = True
                    return
                result = math.sqrt(x)
            elif func == "x²":
                result = x ** 2
            elif func == "x³":
                result = x ** 3
            elif func == "1/x":
                if x == 0:
                    self.current_input = "错误"
                    self.error = True
                    return
                result = 1 / x
            elif func == "π":
                result = math.pi
            elif func == "e":
                result = math.e
            elif func == "!":
                if x < 0 or x != int(x):
                    self.current_input = "错误"
                    self.error = True
                    return
                result = math.factorial(int(x))
            elif func == "sin⁻¹":
                if x < -1 or x > 1:
                    self.current_input = "错误"
                    self.error = True
                    return
                result = math.degrees(math.asin(x))
            elif func == "cos⁻¹":
                if x < -1 or x > 1:
                    self.current_input = "错误"
                    self.error = True
                    return
                result = math.degrees(math.acos(x))
            elif func == "tan⁻¹":
                result = math.degrees(math.atan(x))
            
            # 处理结果
            if result.is_integer():
                self.current_input = str(int(result))
            else:
                # 限制小数位数
                self.current_input = f"{result:.10f}".rstrip('0').rstrip('.')
            
        except Exception as e:
            self.current_input = "错误"
            self.error = True
    
    def memory_store(self):
        try:
            self.memory = float(self.current_input)
        except:
            pass
    
    def memory_recall(self):
        if self.error:
            self.current_input = str(self.memory)
            self.error = False
        else:
            self.current_input = str(self.memory)
    
    def memory_clear(self):
        self.memory = 0
    
    def memory_add(self):
        try:
            self.memory += float(self.current_input)
        except:
            pass
    
    def memory_subtract(self):
        try:
            self.memory -= float(self.current_input)
        except:
            pass
    
    def backspace(self):
        if self.error:
            self.reset()
        elif len(self.current_input) > 1:
            self.current_input = self.current_input[:-1]
        else:
            self.current_input = "0"
    
    def clear(self):
        if self.error:
            self.reset()
        else:
            self.current_input = "0"
    
    def clear_all(self):
        self.reset()

# 按钮类
class Button:
    def __init__(self, x, y, width, height, text, color=COLORS['button_normal'], 
                 hover_color=COLORS['button_hover'], text_color=COLORS['text']):
        self.rect = pygame.Rect(x, y, width, height)
        self.text = text
        self.color = color
        self.hover_color = hover_color
        self.text_color = text_color
        self.is_hovered = False
        self.is_pressed = False
    
    def draw(self, surface):
        # 绘制阴影
        shadow_rect = self.rect.copy()
        shadow_rect.x += 3
        shadow_rect.y += 3
        pygame.draw.rect(surface, COLORS['shadow'], shadow_rect, border_radius=10)
        
        # 绘制按钮
        current_color = self.color
        if self.is_pressed:
            current_color = COLORS['button_press']
        elif self.is_hovered:
            current_color = self.hover_color
        
        pygame.draw.rect(surface, current_color, self.rect, border_radius=10)
        
        # 绘制边框
        pygame.draw.rect(surface, (100, 100, 120), self.rect, 2, border_radius=10)
        
        # 绘制文字
        if len(self.text) <= 3:  # 短文本用大字体
            text_surf = button_font.render(self.text, True, self.text_color)
        else:  # 长文本用小字体
            text_surf = small_font.render(self.text, True, self.text_color)
        
        text_rect = text_surf.get_rect(center=self.rect.center)
        surface.blit(text_surf, text_rect)
    
    def check_hover(self, pos):
        self.is_hovered = self.rect.collidepoint(pos)
        return self.is_hovered
    
    def handle_event(self, event):
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            if self.is_hovered:
                self.is_pressed = True
                return True
        elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:
            self.is_pressed = False
        return False

# 创建计算器实例
calc = Calculator()

# 创建按钮网格
buttons = []

# 基本按钮布局
basic_buttons = [
    # 第一行
    ["C", "CE", "⌫", "÷"],
    # 第二行
    ["7", "8", "9", "×"],
    # 第三行
    ["4", "5", "6", "-"],
    # 第四行
    ["1", "2", "3", "+"],
    # 第五行
    ["±", "0", ".", "="],
]

# 科学函数按钮
scientific_buttons = [
    ["sin", "cos", "tan", "^"],
    ["log", "ln", "√", "%"],
    ["x²", "x³", "1/x", "π"],
    ["e", "!", "sin⁻¹", "cos⁻¹"],
    ["tan⁻¹", "M+", "M-", "MR"],
    ["MC", "MS", "Sci", "Rad"],
]

# 创建按钮
def create_buttons():
    global buttons
    buttons = []
    
    # 基本按钮
    button_width = 80
    button_height = 70
    spacing = 15
    
    start_x = 40
    start_y = 250 if calc.show_scientific else 200
    
    for row_idx, row in enumerate(basic_buttons):
        for col_idx, text in enumerate(row):
            x = start_x + col_idx * (button_width + spacing)
            y = start_y + row_idx * (button_height + spacing)
            
            # 设置按钮颜色
            color = COLORS['button_normal']
            hover_color = COLORS['button_hover']
            
            if text in ["+", "-", "×", "÷", "^", "%"]:
                color = COLORS['operator']
                hover_color = COLORS['operator_hover']
            elif text == "=":
                color = COLORS['equals']
                hover_color = COLORS['equals_hover']
            elif text in ["C", "CE", "⌫"]:
                color = COLORS['clear']
                hover_color = COLORS['clear_hover']
            
            button = Button(x, y, button_width, button_height, text, color, hover_color)
            buttons.append(button)
    
    # 科学函数按钮
    if calc.show_scientific:
        for row_idx, row in enumerate(scientific_buttons):
            for col_idx, text in enumerate(row):
                x = start_x + col_idx * (button_width + spacing)
                y = start_y + (row_idx + len(basic_buttons) + 1) * (button_height + spacing)
                
                color = COLORS['scientific']
                hover_color = COLORS['scientific_hover']
                
                if text in ["M+", "M-", "MR", "MC", "MS"]:
                    color = COLORS['button_normal']
                    hover_color = COLORS['button_hover']
                elif text == "Sci":
                    color = (180, 150, 0)
                    hover_color = (200, 170, 20)
                
                button = Button(x, y, button_width, button_height, text, color, hover_color)
                buttons.append(button)

# 初始创建按钮
create_buttons()

# 主循环
running = True
while running:
    mouse_pos = pygame.mouse.get_pos()
    
    # 事件处理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        
        # 更新按钮悬停状态
        for button in buttons:
            button.check_hover(mouse_pos)
        
        # 处理按钮点击
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            for button in buttons:
                if button.handle_event(event):
                    # 处理按钮点击
                    text = button.text
                    
                    # 数字
                    if text.isdigit():
                        calc.input_digit(text)
                    
                    # 小数点
                    elif text == ".":
                        calc.input_decimal()
                    
                    # 基本运算符
                    elif text in ["+", "-", "×", "÷", "^", "%"]:
                        calc.input_operator(text)
                    
                    # 等号
                    elif text == "=":
                        calc.calculate()
                    
                    # 清除
                    elif text == "C":
                        calc.clear()
                    elif text == "CE":
                        calc.clear_all()
                    
                    # 退格
                    elif text == "⌫":
                        calc.backspace()
                    
                    # 正负号
                    elif text == "±":
                        calc.toggle_sign()
                    
                    # 科学函数
                    elif text in ["sin", "cos", "tan", "log", "ln", "√", 
                                 "x²", "x³", "1/x", "π", "e", "!", 
                                 "sin⁻¹", "cos⁻¹", "tan⁻¹"]:
                        calc.scientific_function(text)
                    
                    # 内存功能
                    elif text == "M+":
                        calc.memory_add()
                    elif text == "M-":
                        calc.memory_subtract()
                    elif text == "MR":
                        calc.memory_recall()
                    elif text == "MC":
                        calc.memory_clear()
                    elif text == "MS":
                        calc.memory_store()
                    
                    # 切换科学模式
                    elif text == "Sci":
                        calc.show_scientific = not calc.show_scientific
                        create_buttons()
                    
                    break
    
    # 绘制背景
    screen.fill(COLORS['background'])
    
    # 绘制标题
    title = button_font.render("高级科学计算器", True, (200, 200, 255))
    screen.blit(title, (WIDTH // 2 - title.get_width() // 2, 20))
    
    # 绘制显示屏
    display_rect = pygame.Rect(40, 80, WIDTH - 80, 100)
    
    # 显示屏阴影
    shadow_rect = display_rect.copy()
    shadow_rect.x += 5
    shadow_rect.y += 5
    pygame.draw.rect(screen, COLORS['shadow'], shadow_rect, border_radius=15)
    
    # 显示屏背景
    pygame.draw.rect(screen, COLORS['display'], display_rect, border_radius=15)
    pygame.draw.rect(screen, (80, 80, 100), display_rect, 3, border_radius=15)
    
    # 显示当前输入
    if len(calc.current_input) > 20:
        display_text = display_font.render(calc.current_input[-20:], True, COLORS['display_text'])
    else:
        display_text = display_font.render(calc.current_input, True, COLORS['display_text'])
    
    text_rect = display_text.get_rect(right=display_rect.right - 20, centery=display_rect.centery)
    screen.blit(display_text, text_rect)
    
    # 显示运算表达式
    if calc.operator:
        expression = f"{calc.previous_input} {calc.operator}"
        expr_text = small_font.render(expression, True, (150, 150, 180))
        screen.blit(expr_text, (display_rect.left + 20, display_rect.top + 10))
    
    # 显示内存值
    memory_text = small_font.render(f"M: {calc.memory}", True, (150, 150, 180))
    screen.blit(memory_text, (display_rect.right - 100, display_rect.top + 10))
    
    # 显示模式
    mode_text = small_font.render("科学模式" if calc.show_scientific else "基本模式", 
                                 True, (150, 150, 180))
    screen.blit(mode_text, (display_rect.left + 20, display_rect.bottom - 30))
    
    # 绘制所有按钮
    for button in buttons:
        button.draw(screen)
    
    # 绘制说明文字
    if not calc.show_scientific:
        help_text = small_font.render("点击 'Sci' 按钮切换到科学模式", True, (180, 180, 200))
        screen.blit(help_text, (WIDTH // 2 - help_text.get_width() // 2, HEIGHT - 40))
    else:
        help_text = small_font.render("科学模式已启用 - 点击 'Sci' 返回基本模式", True, (180, 180, 200))
        screen.blit(help_text, (WIDTH // 2 - help_text.get_width() // 2, HEIGHT - 40))
    
    # 更新显示
    pygame.display.flip()
    clock.tick(60)

# 退出 Pygame
pygame.quit()
sys.exit()