Recreate this GUI in pygame: import sys
import re
import threading
import io
import contextlib
from PyQt6.QtCore import QObject, QThread, pyqtSignal, Qt, QTimer
from PyQt6.QtWidgets import (
    QApplication, QWidget, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit,
    QPushButton, QSlider, QTextEdit, QProgressBar, QMessageBox, QGroupBox
)
from gradio_client import Client


class Worker(QObject):
    finished = pyqtSignal()
    result_ready = pyqtSignal(str, str)
    execution_result = pyqtSignal(str)
    save_code_finished = pyqtSignal()

    def __init__(self, client, inputs=None, top_p=None, temperature=None, retries=5):
        super().__init__()
        self.client = client
        self.inputs = inputs
        self.top_p = top_p
        self.temperature = temperature
        self.retries = retries
        self.api_call_count = 0

    def run(self):
        if self.inputs:
            self.run_prediction()
        else:
            self.save_code()

    def run_prediction(self):
        try_count = 0
        while try_count < self.retries:
            try:
                self.api_call_count += 1
                result = self.client.predict(
                    inputs=self.inputs,
                    top_p=self.top_p,
                    temperature=self.temperature,
                    chat_counter=self.api_call_count,
                    chatbot=[],
                    api_name="/predict"
                )
                response_text = result[0][0][1]
                code = self.extract_code(response_text)

                # Emit result only if code is valid
                if self.is_valid_code(code):
                    self.result_ready.emit(response_text, code)
                    exec_output = self.execute_code(code)
                    self.execution_result.emit(exec_output)
                else:
                    self.result_ready.emit(response_text, "")
                    self.execution_result.emit("Extracted code is invalid.")

                break
            except Exception as e:
                self.result_ready.emit(f"Error: {str(e)}", "")
                self.execution_result.emit(f"Execution error: {str(e)}")
            try_count += 1
        self.finished.emit()

    def save_code(self):
        filename, code = self.inputs  # inputs contains filename and code tuple
        try:
            with open(filename, 'w') as f:
                f.write(code)
            self.save_code_finished.emit()
        except Exception as e:
            QMessageBox.warning(None, "Error", f"Failed to save code: {str(e)}")

    def extract_code(self, text):
        pattern = r'```python(.*?)```'
        matches = re.findall(pattern, text, re.DOTALL)
        return "\n".join(match.strip() for match in matches) if matches else "No valid code found."

    def is_valid_code(self, code):
        return bool(code.strip()) and len(code.splitlines()) >= 2

    def execute_code(self, code):
        if not self.is_valid_code(code):
            return "No valid code to execute."

        try:
            output = io.StringIO()
            with contextlib.redirect_stdout(output):
                exec(code, globals())
            return output.getvalue() if output.getvalue() else "Code executed without output."
        except Exception as e:
            return f"Execution error: {str(e)}"


class ChatGPTApp(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("ChatGPT API Interface")
        self.resize(900, 700)

        self.client = Client("yuntian-deng/ChatGPT")
        self.initUI()
        self.api_call_counter = 0

    def initUI(self):
        layout = QVBoxLayout()
        
        # Group for input and parameters
        input_group = QGroupBox("Input & Parameters")
        input_layout = QVBoxLayout()
        
        self.input_field = QLineEdit(self)
        self.input_field.setPlaceholderText("Type your message here...")

        top_p_layout = QHBoxLayout()
        self.top_p_slider = QSlider(Qt.Orientation.Horizontal)
        self.top_p_slider.setRange(0, 100)
        self.top_p_slider.setValue(100)
        top_p_layout.addWidget(QLabel("Top-p:"))
        top_p_layout.addWidget(self.top_p_slider)

        temperature_layout = QHBoxLayout()
        self.temperature_slider = QSlider(Qt.Orientation.Horizontal)
        self.temperature_slider.setRange(0, 100)
        self.temperature_slider.setValue(100)
        temperature_layout.addWidget(QLabel("Temperature:"))
        temperature_layout.addWidget(self.temperature_slider)

        self.filename_field = QLineEdit(self)
        self.filename_field.setPlaceholderText("Enter filename to save code (e.g., output.py)")

        self.predict_button = QPushButton("Predict", self)
        self.predict_button.clicked.connect(self.start_prediction_thread)

        self.save_execute_button = QPushButton("Save and Execute Code", self)
        self.save_execute_button.clicked.connect(self.save_and_execute_code)

        # Add to input layout
        input_layout.addWidget(self.input_field)
        input_layout.addLayout(top_p_layout)
        input_layout.addLayout(temperature_layout)
        input_layout.addWidget(self.filename_field)
        input_layout.addWidget(self.predict_button)
        input_layout.addWidget(self.save_execute_button)

        input_group.setLayout(input_layout)

        # Group for response areas
        response_group = QGroupBox("Response Areas")
        response_layout = QVBoxLayout()

        self.response_area = QTextEdit(self)
        self.response_area.setReadOnly(True)

        self.code_area = QTextEdit(self)
        self.code_area.setReadOnly(True)
        
        self.execution_area = QTextEdit(self)
        self.execution_area.setReadOnly(True)
        
        response_layout.addWidget(QLabel("Response:"))
        response_layout.addWidget(self.response_area)
        response_layout.addWidget(QLabel("Extracted Code:"))
        response_layout.addWidget(self.code_area)
        response_layout.addWidget(QLabel("Execution Result:"))
        response_layout.addWidget(self.execution_area)

        response_group.setLayout(response_layout)

        # Progress Bar and API Call Counter
        self.api_counter_label = QLabel("API Call Count: 0")
        self.progress_bar = QProgressBar(self)
        self.progress_bar.setRange(0, 0)
        self.flashing_lights_label = QLabel("Processing...")
        self.flashing_lights_timer = QTimer()
        self.flashing_lights_timer.timeout.connect(self.toggle_flashing_lights)
        self.flashing_lights_timer.start(500)

        layout.addWidget(input_group)
        layout.addWidget(response_group)
        layout.addWidget(self.api_counter_label)
        layout.addWidget(self.progress_bar)
        layout.addWidget(self.flashing_lights_label)

        self.setLayout(layout)

    def toggle_flashing_lights(self):
        current_color = self.flashing_lights_label.styleSheet()
        new_color = "color: red;" if current_color != "color: red;" else "color: black;"
        self.flashing_lights_label.setStyleSheet(new_color)

    def start_prediction_thread(self):
        inputs = self.input_field.text()
        if not inputs.strip():
            QMessageBox.warning(self, "Warning", "Please enter a message before predicting.")
            return

        top_p = self.top_p_slider.value() / 100.0
        temperature = self.temperature_slider.value() / 100.0

        self.thread = QThread()
        self.worker = Worker(self.client, inputs, top_p, temperature)

        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.run)
        self.worker.finished.connect(self.thread.quit)
        self.worker.result_ready.connect(self.update_ui)
        self.worker.execution_result.connect(self.update_execution_result)

        self.api_call_counter += 1
        self.api_counter_label.setText(f"API Call Count: {self.api_call_counter}")
        
        self.progress_bar.setValue(0)
        self.progress_bar.setRange(0, 0)
        self.flashing_lights_timer.start()
        self.thread.start()

    def save_and_execute_code(self):
        code = self.code_area.toPlainText()
        filename = self.filename_field.text()
        
        if not filename:
            QMessageBox.warning(self, "Warning", "Please enter a filename to save the code.")
            return
        
        inputs = (filename, code)
        self.thread = QThread()
        self.worker = Worker(self.client, inputs=inputs)  # Create worker for saving code
        self.worker.moveToThread(self.thread)
        self.thread.started.connect(self.worker.run)
        self.worker.save_code_finished.connect(self.on_code_saved)

        self.thread.finished.connect(self.thread.deleteLater)
        self.worker.finished.connect(self.worker.deleteLater)

        self.thread.start()

    def on_code_saved(self):
        QMessageBox.information(self, "Success", "Code saved successfully!")

    def update_ui(self, response_text, code):
        self.response_area.setPlainText(response_text)
        self.code_area.setPlainText(code)
        self.progress_bar.setRange(0, 1)
        self.flashing_lights_timer.stop()

    def update_execution_result(self, execution_result):
        self.execution_area.setPlainText(execution_result)
        self.progress_bar.setRange(0, 1)
        self.flashing_lights_timer.stop()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = ChatGPTApp()
    window.show()
    sys.exit(app.exec())