from numpy import where

from GUIBRUSHR.GUI.WIDGET.MyLabel import MyLabel
from GUIBRUSHR.GUI.WIDGET.MyDropDown import MyDropdown
from GUIBRUSHR.GUI.WIDGET.MyCheckBox import MyCheckBox
from GUIBRUSHR.GUI.WIDGET.MyEntry import MyEntry


class ParamClassForManualPlot:
    """
    A simplified class to handle manual plot parameters in the GUI.

    This class manages parameter widgets with only the essential fields:
    - Name (label or dropdown for molecules)
    - Present (checkbox)
    - Value (entry field)
    - Type (Linear/Log10 label)
    """

    def __init__(
        self,
        parent,
        row,
        col,
        name,
        value,
        present,
        status,
        molec_line=None,
        mass_molec=None,
        color=None,
        molecs=None,
        isotopes=None,
        opacity_line_lists=None,
        isotope_masses=None,
        rayleigh=False,
        type_params="Linear",
        single_dropdown=False
    ):
        """
        Initialize the parameter panel for manual plotting.

        Args:
            parent: Parent panel for the parameter
            row: Row position in the grid
            col: Column position in the grid
            name: Name of the parameter
            value: Initial value of the parameter
            present: Initial presence state
            status: Initial status of the parameter
            molec_line: If not None, creates molecular selection dropdowns
            mass_molec: Molecular mass (stored but not displayed)
            color: Color scheme for the panel
            molecs: List of molecules (for dropdown)
            isotopes: Dictionary of isotopes (for dropdown)
            opacity_line_lists: Dictionary of opacity_line_lists (for dropdown)
            isotope_masses: Dictionary of isotope masses
            rayleigh: Rayleigh flag (stored but not displayed)
            type_params: Type of parameters ("Linear" or "Log10")
            single_dropdown: If True with molec_line, creates only one dropdown instead of three
        """
        self.parent = parent
        self.row = row
        self.color = color
        self.selected_molec = 0
        self.single_dropdown = single_dropdown

        # Initialize dropdown attributes (may be set by _setup_molecular_parameters)
        self.dropdown_molec = None
        self.dropdown_isotope = None
        self.dropdown_opacity_line_list_HR = None
        self.label_name = None

        if present >= 1:
            present = 1

        # Column positioning starts from col parameter
        current_col = col

        # Initialize name widgets (either label or molecular dropdowns)
        if molec_line is None:
            # Simple parameter: just show name label
            self.label_name = MyLabel(
                parent, row, current_col, label_text=name, columnspan=3, color=color
            )
            self.name_for_retrieval = name
            self.molec_formula = None
            mass = mass_molec
            current_col += 3
        else:
            # Molecular parameter: show dropdowns
            if single_dropdown:
                # Single dropdown mode (for condensed molecules)
                self._setup_single_dropdown(molecs, isotope_masses, color, current_col)
                mass = self.isotope_masses[self.molecs[0]]
                self.molec_formula = self.molecs[0]
                self.name_for_retrieval = None
                current_col += 3  # Single dropdown takes same space
            else:
                # Three dropdowns mode (for regular molecules)
                self._setup_molecular_parameters(
                    molecs, isotopes, opacity_line_lists, isotope_masses, color, current_col
                )
                mass = self.isotope_masses[self.isotopes[self.molecs[0]][0]]
                self.molec_formula = self.molecs[0]
                self.name_for_retrieval = None
                current_col += 3  # molecule, isotope, opacity_line_list dropdowns

        # Store molecular information
        self.molec_line = molec_line
        self.mass_molec = mass

        # Presence checkbox
        self.checkbox_presence = MyCheckBox(
            parent, row, current_col, "", initial_value=present
        )
        current_col += 1

        # Value entry
        self.entry_value = MyEntry(
            parent, row, current_col, str(value),
            color=color, columnspan=2, entry_width=10
        )
        current_col += 2

        # Type label
        self.label_type = MyLabel(
            parent, row, current_col,
            color=color, label_text=type_params
        )
        current_col += 1

        # Rayleigh dropdown (only for molecules with mass, not condensed)
        if mass is not None and not single_dropdown:
            self.dropdown_rayleigh = MyDropdown(
                parent, row, current_col, ["0", "1", "2"], color=color, columnspan=1
            )
            self.dropdown_rayleigh.chosen_var.set(str(int(rayleigh)))
            self._rayleigh_fixed = None
        else:
            self.dropdown_rayleigh = None
            self._rayleigh_fixed = 0
            MyLabel(parent, row, current_col, label_text="—", columnspan=1, color=color)

        # VMR flag (for compatibility with existing code)
        self.VMR = True

        # Initialize status
        self.disabled = 0
        self.parameter_status(status)

    def _setup_single_dropdown(self, molecs, isotope_masses, color, col):
        """Setup single dropdown for condensed molecules (no isotopes/opacity_line_lists)."""
        self.molecs = molecs
        self.isotope_masses = isotope_masses

        # No isotopes/opacity_line_lists for single dropdown mode
        self.isotopes = None
        self.opacity_line_lists = None

        # Store column position
        self.col_molec = col

        # Setup single molecule dropdown spanning 3 columns
        self.dropdown_molec = MyDropdown(
            self.parent, self.row, self.col_molec, self.molecs, columnspan=3, color=color
        )
        # Add trace to update mass when selection changes
        self.dropdown_molec.chosen_var.trace("w", lambda *args: self.on_select_single_dropdown())

    def _setup_molecular_parameters(self, molecs, isotopes, opacity_line_lists, isotope_masses, color, col):
        """Setup molecular-related parameters and dropdowns."""
        self.molecs = molecs
        self.isotopes = isotopes
        self.opacity_line_lists = opacity_line_lists
        self.isotope_masses = isotope_masses

        # Store column positions for rebuilding dropdowns
        self.col_molec = col
        self.col_isotope = col + 1
        self.col_opacity_line_list = col + 2

        # Setup molecule dropdown
        self.dropdown_molec = MyDropdown(
            self.parent, self.row, self.col_molec, self.molecs, columnspan=1, color=color
        )
        self.dropdown_molec.chosen_var.trace("w", lambda *args: self.on_select_molec())

        # Setup isotope dropdown
        self.dropdown_isotope = MyDropdown(
            self.parent, self.row, self.col_isotope,
            self.isotopes[self.molecs[0]], columnspan=1, color=color
        )
        self.dropdown_isotope.chosen_var.trace("w", lambda *args: self.on_select_isotope())

        # Setup opacity_line_list dropdown
        self.dropdown_opacity_line_list_HR = MyDropdown(
            self.parent, self.row, self.col_opacity_line_list,
            self.opacity_line_lists[self.isotopes[self.molecs[0]][0]], columnspan=1, color=color
        )

    def get_rayleigh_value(self):
        """Get the rayleigh value: from dropdown if molecule, otherwise fixed value."""
        if self.dropdown_rayleigh is not None:
            return int(self.dropdown_rayleigh.get_value())
        return self._rayleigh_fixed

    def parameter_status(self, state):
        """Update the status of parameter widgets."""
        self.entry_value.entry.configure(state=state)
        self.checkbox_presence.checkbox.configure(state=state)
        if self.dropdown_rayleigh is not None:
            self.dropdown_rayleigh.set_status(state)
        self.disabled = 1 if state == "disabled" else 0

    def get_name(self):
        """Get the name and molecular information for retrieval."""
        name_for_retrieval = None
        molec = None

        if self.name_for_retrieval is not None:
            # Simple parameter (no dropdowns)
            name = self.name_for_retrieval
            if self.mass_molec is not None:
                molec = name
                name_for_retrieval = name
        else:
            # Molecular parameter (has dropdowns)
            name = molec = self.molec_formula
            if self.single_dropdown:
                # Single dropdown mode: just use the selected molecule
                name_for_retrieval = self.dropdown_molec.get_value()
            else:
                # Three dropdown mode: use sub-isotope
                name_for_retrieval = self.dropdown_opacity_line_list_HR.get_value()

        return name, name_for_retrieval, molec

    def get_value(self):
        """Get the parameter value(s)."""
        str_param = self.entry_value.get_value()
        if "," in str_param:
            params = [float(elem) for elem in str_param.split(",")]
        else:
            params = float(self.entry_value.get_value())
        return params

    def is_considered(self):
        """Check if the parameter should be considered in calculations."""
        return (not self.disabled) and self.checkbox_presence.get_value()

    def on_select_single_dropdown(self):
        """Handle single dropdown selection change (for condensed molecules)."""
        selected_value = self.dropdown_molec.get_value()
        # Update mass and formula
        self.mass_molec = self.isotope_masses[selected_value]
        self.molec_formula = selected_value

    def on_select_isotope(self):
        """Handle isotope selection change."""
        selected_index = where(
            self.isotopes[self.molecs[self.selected_molec]] == self.dropdown_isotope.get_value()
        )[0][0]

        self.dropdown_opacity_line_list_HR.clean_widget()
        mass = self.isotope_masses[self.isotopes[self.molecs[self.selected_molec]][selected_index]]
        self.mass_molec = mass

        self.dropdown_opacity_line_list_HR = MyDropdown(
            self.parent, self.row, self.col_opacity_line_list,
            self.opacity_line_lists[self.isotopes[self.molecs[self.selected_molec]][selected_index]],
            columnspan=1, color=self.color
        )

    def on_select_molec(self):
        """Handle molecule selection change."""
        selected_index = where(self.molecs == self.dropdown_molec.get_value())[0][0]

        # Clean existing widgets
        self.dropdown_isotope.clean_widget()
        self.dropdown_opacity_line_list_HR.clean_widget()

        # Update selection
        self.selected_molec = selected_index
        self.molec_formula = self.molecs[self.selected_molec]

        # Update mass
        mass = self.isotope_masses[self.isotopes[self.molecs[selected_index]][0]]
        self.mass_molec = mass

        # Create new dropdowns
        self.dropdown_isotope = MyDropdown(
            self.parent, self.row, self.col_isotope,
            self.isotopes[self.molecs[selected_index]], columnspan=1, color=self.color
        )
        self.dropdown_opacity_line_list_HR = MyDropdown(
            self.parent, self.row, self.col_opacity_line_list,
            self.opacity_line_lists[self.isotopes[self.molecs[selected_index]][0]],
            columnspan=1, color=self.color
        )
        self.dropdown_isotope.chosen_var.trace("w", lambda *args: self.on_select_isotope())
