import os
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QPlainTextEdit, 
                             QPushButton, QHBoxLayout, QFileDialog, QMessageBox, QSizePolicy, QStackedWidget, QProgressBar)
from PyQt5.QtCore import QFileSystemWatcher, Qt, pyqtSignal, QTimer
from PyQt5.QtGui import QFont

class GCodeEditor(QWidget):
    
    editor_closed = pyqtSignal()  # Signal emitted when editor closes
    def __init__(self, parent=None, filename=None):
        super().__init__(parent, Qt.Window)  # Important: Qt.Window flag
        self.filename = filename
        self.initialize_stylesheets()
        self.setup_ui()
        self.load_file()
        self.setup_file_watcher()
        
    def setup_ui(self):
        self.setWindowTitle("G-code Editor - " + os.path.basename(self.filename))
        self.setGeometry(100, 100, 800, 600)
        
         # Progress Bar
        self.progress_bar = QProgressBar()
        self.progress_bar.setStyleSheet(self.stylesheet_progress_bar)
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setTextVisible(True)

        self.AlterWidget = QStackedWidget()

        layout = QVBoxLayout()
        
        # Text editor
        self.text_edit = QPlainTextEdit()
        self.text_edit.setStyleSheet(self.stylesheet_textBox)
        
        self.text_edit.setFont(QFont("Courier New", 15))
        self.text_edit.textChanged.connect(self.on_text_changed)
        layout.addWidget(self.text_edit)
        
        # Button row
        button_layout = QHBoxLayout()

        self.send_gcode_file = QPushButton("Send G-Code File to RobotArm")
        self.send_gcode_file.setStyleSheet(self.stylesheet_send_serial_button)
        self.send_gcode_file.adjustSize()
        
        utility_widget = QWidget()

        utility_layout = QHBoxLayout()

        utility_layout.setContentsMargins(0,0,0,0)

        utility_widget.setLayout(utility_layout)

        self.save_button = QPushButton("Save")
        self.save_button.setStyleSheet(self.stylesheet_button)
       #self.save_button.setMinimumWidth(60)
        self.save_button.adjustSize()
        self.save_as_button = QPushButton("Save File As")
        self.save_as_button.setStyleSheet(self.stylesheet_button)
        #self.save_as_button.setSizePolicy(QSizePolicy.Policy.Maximum,QSizePolicy.Policy.Maximum)
        self.save_as_button.adjustSize()
        self.reload_button = QPushButton("Reload")
        self.reload_button.setStyleSheet(self.stylesheet_button)
        self.reload_button.adjustSize()
        self.reload_button.setSizePolicy(QSizePolicy.Policy.Maximum,QSizePolicy.Policy.Maximum)
        self.load_button = QPushButton("load")
        self.load_button.setStyleSheet(self.stylesheet_button)
        self.load_button.adjustSize()
        self.load_button.setSizePolicy(QSizePolicy.Policy.Maximum,QSizePolicy.Policy.Maximum)
        
        self.save_button.clicked.connect(self.save_file)
        self.save_as_button.clicked.connect(self.save_as_file)
        self.reload_button.clicked.connect(self.load_file)
        self.load_button.clicked.connect(self.extern_load)
        
        self.AlterWidget.addWidget(utility_widget)
        self.AlterWidget.addWidget(self.progress_bar)
        self.AlterWidget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Maximum)

        button_layout.addWidget(self.send_gcode_file)
        utility_layout.addWidget(self.save_button)
        utility_layout.addWidget(self.save_as_button)
        utility_layout.addWidget(self.load_button)
        utility_layout.addWidget(self.reload_button, Qt.AlignmentFlag.AlignRight)
        button_layout.addWidget(self.AlterWidget, Qt.AlignmentFlag.AlignRight)
        #button_layout.addStretch()  # Push buttons to left
        
        layout.addLayout(button_layout)
        self.setLayout(layout)

        
    
    def extern_load(self):
        """Open file dialog to select G-code file and copy contents to temp file"""
        # Open file dialog to select G-code file
        filename_extern, _ = QFileDialog.getOpenFileName(
            self, 
            "Select G-code File to Import",
            "",  # Start in current directory
            "G-code Files (*.gcode *.nc *.txt);;All Files (*)"  # File filters
        )
        
        # If user cancelled the dialog
        if not filename_extern:
            return
        
        try:
            # Read the selected file
            with open(filename_extern, 'r', encoding='utf-8') as source_file:
                content = source_file.read()
            
            # Write to temp file
            with open(self.filename, 'w', encoding='utf-8') as temp_file:
                temp_file.write(content)
            
            # Update the editor with the new content
            self.text_edit.setPlainText(content)
            self.text_edit.document().setModified(False)
            self.on_text_changed()  # Update window title
            
            # Show success message
            QMessageBox.information(self, "Success", 
                                f"Imported G-code from {os.path.basename(filename_extern)}")
            
        except Exception as e:
            QMessageBox.critical(self, "Error", f"Could not import file: {e}")

    def on_text_changed(self):
        """Update window title to show modified state"""
        modified = self.text_edit.document().isModified()
        base_title = "G-code Editor - " + os.path.basename(self.filename)
        self.setWindowTitle(base_title + (" *" if modified else ""))

        # Always scroll to bottom when text changes
        scrollbar = self.text_edit.verticalScrollBar()
        if scrollbar:
            scrollbar.setValue(scrollbar.maximum())
    
    def load_file(self):
        try:
            with open(self.filename, 'r') as f:
                content = f.read()
            self.text_edit.setPlainText(content)
            self.text_edit.document().setModified(False)
            self.on_text_changed()  # Update title

            # Scroll to bottom after loading
            QTimer.singleShot(100, self.scroll_to_bottom)
            
        except Exception as e:
            QMessageBox.warning(self, "Error", f"Could not read file: {e}")

    def scroll_to_bottom(self):
        scrollbar = self.text_edit.verticalScrollBar()
        if scrollbar:
                    scrollbar.setValue(scrollbar.maximum())
    
    def save_file(self):
        try:
            content = self.text_edit.toPlainText()
            with open(self.filename, 'w') as f:
                f.write(content)
            self.text_edit.document().setModified(False)
            self.on_text_changed()  # Update title
        except Exception as e:
            QMessageBox.critical(self, "Error", f"Could not save file: {e}")
    
    def save_as_file(self):
        filename, _ = QFileDialog.getSaveFileName(
            self, "Save G-code File", "", "G-code Files (*.gcode *.nc *.txt)"
        )
        if filename:
            try:
                content = self.text_edit.toPlainText()
                with open(filename, 'w') as f:
                    f.write(content)
                self.text_edit.document().setModified(False)
                self.on_text_changed()  # Update title with new filename
            except Exception as e:
                QMessageBox.critical(self, "Error", f"Could not save file: {e}")
    
    def setup_file_watcher(self):
        self.file_watcher = QFileSystemWatcher([self.filename])
        self.file_watcher.fileChanged.connect(self.on_file_changed_externally)
    
    def on_file_changed_externally(self, path):
        """Handle external file modifications"""
        if self.text_edit.document().isModified():
            reply = QMessageBox.question(
                self, "File Changed",
                "The file has been modified externally. Reload and lose your changes?",
                QMessageBox.Yes | QMessageBox.No
            )
            if reply == QMessageBox.Yes:
                self.load_file()
        else:
            self.load_file()
    
    def closeEvent(self, event):
        """Handle window close with unsaved changes"""
        if self.text_edit.document().isModified():
            reply = QMessageBox.question(
                self, "Unsaved Changes",
                "You have unsaved changes. Save before closing?",
                QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel
            )
            
            if reply == QMessageBox.Save:
                self.save_file()
                self.editor_closed.emit()  # Emit after saving
                event.accept()
            elif reply == QMessageBox.Discard:
                self.editor_closed.emit()  # Emit before closing
                event.accept()
            else:
                event.ignore()
        else:
            self.editor_closed.emit()  # Emit before closing
            event.accept()
    
    def initialize_stylesheets(self):

        self.stylesheet_textBox = """color: #bbbbbb;
                                        border: 4px solid #626262;
                                        border-radius: 4px;
                                        padding: 2px;"""
        self.stylesheet_button = """QPushButton {
                                                Background-Color: #747474;  
                                                Border-radius: 4px;                   
                                                Border: 3px solid #adadad;  
                                                padding: 4px;
                                                margin: 2px;                         
                                                                
                                            }
                                            
                                            /* Pressed state style */
                                            QPushButton:pressed {
                                                background-color: #5b5b5b;  
                                            }"""
        
        self.stylesheet_send_serial_button = """
                                            /* Base button style */
                                            QPushButton {
                                                Background-Color: rgb(189, 132, 27);  /* Orange-brown background */
                                                Border-radius: 4px;                   /* Slightly rounded corners */
                                                Border: 3px solid rgb(255, 176, 66);  /* Brighter orange border */
                                                padding: 4px;
                                                margin: 2px;                          /* External spacing */
                                                                
                                            }
                                            
                                            /* Pressed state style */
                                            QPushButton:pressed {
                                                background-color: rgb(158, 106, 24);  /* Darker shade when pressed */
                                            }
                                        """
        
        self.stylesheet_progress_bar = """
        QProgressBar {
            border: 2px solid #5c5c5c;
            border-radius: 5px;
            background-color: #2d2d2d;
            text-align: center;
            color: #ffffff;
            font-weight: bold;
        }
        QProgressBar::chunk {
            background-color: #179999;
            border-radius: 3px;
        }
    """
    
