""" Searchable Healing Tool Selector for Lemontropia Suite Browse and search healing tools from Entropia Nexus API """ from decimal import Decimal from PyQt6.QtWidgets import ( QDialog, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QTreeWidget, QTreeWidgetItem, QHeaderView, QLabel, QDialogButtonBox, QProgressBar, QGroupBox, QFormLayout, QComboBox ) from PyQt6.QtCore import Qt, QThread, pyqtSignal from PyQt6.QtGui import QColor from typing import Optional, List from core.nexus_full_api import get_nexus_api, NexusHealingTool class HealingLoaderThread(QThread): """Background thread for loading healing tools from API.""" tools_loaded = pyqtSignal(list) error_occurred = pyqtSignal(str) def run(self): try: api = get_nexus_api() tools = api.get_all_healing_tools() self.tools_loaded.emit(tools) except Exception as e: self.error_occurred.emit(str(e)) class HealingSelectorDialog(QDialog): """Dialog for selecting healing tools from Entropia Nexus API with search.""" tool_selected = pyqtSignal(NexusHealingTool) def __init__(self, parent=None): super().__init__(parent) self.setWindowTitle("Select Healing Tool - Entropia Nexus") self.setMinimumSize(900, 600) self.all_tools: List[NexusHealingTool] = [] self.selected_tool: Optional[NexusHealingTool] = None self._setup_ui() self._load_data() def _setup_ui(self): layout = QVBoxLayout(self) layout.setSpacing(10) # Status self.status_label = QLabel("Loading healing tools from Entropia Nexus...") layout.addWidget(self.status_label) self.progress = QProgressBar() self.progress.setRange(0, 0) layout.addWidget(self.progress) # Filters filter_layout = QHBoxLayout() filter_layout.addWidget(QLabel("Type:")) self.type_combo = QComboBox() self.type_combo.addItems(["All Types", "FAP (Medical Tool)", "Restoration Chip", "Limited (L)"]) self.type_combo.currentTextChanged.connect(self._apply_filters) filter_layout.addWidget(self.type_combo) filter_layout.addWidget(QLabel("Min Heal:")) self.min_heal_combo = QComboBox() self.min_heal_combo.addItems(["Any", "10+", "25+", "50+", "75+", "100+"]) self.min_heal_combo.currentTextChanged.connect(self._apply_filters) filter_layout.addWidget(self.min_heal_combo) layout.addLayout(filter_layout) # Search search_layout = QHBoxLayout() search_layout.addWidget(QLabel("Search:")) self.search_input = QLineEdit() self.search_input.setPlaceholderText("Type to search healing tools...") self.search_input.textChanged.connect(self._apply_filters) search_layout.addWidget(self.search_input) self.clear_btn = QPushButton("Clear") self.clear_btn.clicked.connect(self._clear_search) search_layout.addWidget(self.clear_btn) layout.addLayout(search_layout) # Results tree self.results_tree = QTreeWidget() self.results_tree.setHeaderLabels([ "Name", "Type", "Heal Amount", "Decay (PEC)", "Economy (hp/pec)", "Prof. Level", "Limited" ]) header = self.results_tree.header() header.setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) header.setStretchLastSection(False) self.results_tree.itemSelectionChanged.connect(self._on_selection_changed) self.results_tree.itemDoubleClicked.connect(self._on_double_click) layout.addWidget(self.results_tree) # Preview panel self.preview_group = QGroupBox("Healing Tool Preview") preview_layout = QFormLayout(self.preview_group) self.preview_name = QLabel("-") self.preview_heal = QLabel("-") self.preview_decay = QLabel("-") self.preview_economy = QLabel("-") self.preview_cost = QLabel("-") preview_layout.addRow("Name:", self.preview_name) preview_layout.addRow("Heal Amount:", self.preview_heal) preview_layout.addRow("Decay:", self.preview_decay) preview_layout.addRow("Economy:", self.preview_economy) preview_layout.addRow("Cost/Heal:", self.preview_cost) layout.addWidget(self.preview_group) # Buttons buttons = QDialogButtonBox( QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel ) buttons.accepted.connect(self._on_accept) buttons.rejected.connect(self.reject) self.ok_button = buttons.button(QDialogButtonBox.StandardButton.Ok) self.ok_button.setEnabled(False) layout.addWidget(buttons) def _load_data(self): """Load healing tools in background thread.""" self.loader = HealingLoaderThread() self.loader.tools_loaded.connect(self._on_tools_loaded) self.loader.error_occurred.connect(self._on_load_error) self.loader.start() def _on_tools_loaded(self, tools: List[NexusHealingTool]): """Handle loaded tools.""" self.all_tools = tools self.status_label.setText(f"Loaded {len(tools)} healing tools from Entropia Nexus") self.progress.setRange(0, 100) self.progress.setValue(100) self._apply_filters() def _on_load_error(self, error: str): """Handle load error.""" self.status_label.setText(f"Error loading healing tools: {error}") self.progress.setRange(0, 100) self.progress.setValue(0) def _apply_filters(self): """Apply all filters and search.""" tools = self.all_tools.copy() # Type filter type_filter = self.type_combo.currentText() if type_filter == "FAP (Medical Tool)": tools = [t for t in tools if t.type == 'fap'] elif type_filter == "Restoration Chip": tools = [t for t in tools if 'chip' in t.type.lower()] elif type_filter == "Limited (L)": tools = [t for t in tools if t.is_limited] # Min heal filter min_heal = self.min_heal_combo.currentText() if min_heal != "Any": min_val = int(min_heal.replace("+", "")) tools = [t for t in tools if t.heal_amount >= min_val] # Search filter search_text = self.search_input.text() if search_text: query = search_text.lower() tools = [t for t in tools if query in t.name.lower()] self._populate_results(tools) # Update status if search_text: self.status_label.setText(f"Found {len(tools)} tools matching '{search_text}'") else: self.status_label.setText(f"Showing {len(tools)} of {len(self.all_tools)} tools") def _populate_results(self, tools: List[NexusHealingTool]): """Populate results tree.""" self.results_tree.clear() # Sort by economy (best first) tools = sorted(tools, key=lambda t: t.heal_per_pec, reverse=True) for tool in tools: item = QTreeWidgetItem() item.setText(0, tool.name) item.setText(1, tool.type) item.setText(2, str(tool.heal_amount)) item.setText(3, f"{tool.decay:.2f}") item.setText(4, f"{tool.heal_per_pec:.2f}") item.setText(5, str(tool.profession_level) if tool.profession_level > 0 else "-") item.setText(6, "Yes" if tool.is_limited else "No") # Color code by economy (green = good, red = bad) if tool.heal_per_pec >= 20: item.setForeground(4, QColor("#4caf50")) # Green elif tool.heal_per_pec >= 15: item.setForeground(4, QColor("#ff9800")) # Orange else: item.setForeground(4, QColor("#f44336")) # Red item.setData(0, Qt.ItemDataRole.UserRole, tool) self.results_tree.addTopLevelItem(item) def _clear_search(self): """Clear search and filters.""" self.search_input.clear() self.type_combo.setCurrentIndex(0) self.min_heal_combo.setCurrentIndex(0) self._apply_filters() def _on_selection_changed(self): """Handle selection change.""" items = self.results_tree.selectedItems() if items: self.selected_tool = items[0].data(0, Qt.ItemDataRole.UserRole) self.ok_button.setEnabled(True) self._update_preview(self.selected_tool) else: self.selected_tool = None self.ok_button.setEnabled(False) def _update_preview(self, tool: NexusHealingTool): """Update preview panel.""" self.preview_name.setText(tool.name) self.preview_heal.setText(f"{tool.heal_amount} HP") self.preview_decay.setText(f"{tool.decay:.2f} PEC") self.preview_economy.setText(f"{tool.heal_per_pec:.2f} hp/pec") self.preview_cost.setText(f"{tool.decay / Decimal('100'):.4f} PED") def _on_double_click(self, item, column): """Handle double click.""" self._on_accept() def _on_accept(self): """Handle OK button.""" if self.selected_tool: self.tool_selected.emit(self.selected_tool) self.accept()