from qgis.PyQt.QtWidgets import QComboBox, QGridLayout, QLabel, QTableView, QWidget

from openlog.datamodel.assay.generic_assay import AssayDatabaseDefinition
from openlog.toolbelt.string_map_table_model import StringMapTableModel


class AssayDatabaseDefinitionWidget(QWidget):
    HOLE_COL_DEFAULT = "hole"
    DATASET_COL_DEFAULT = "dataset"
    PERSON_COL_DEFAULT = "person"
    IMPORT_DATE_COL_DEFAULT = "import_date"
    X_COL_DEFAULT = "x"
    X_END_COL_DEFAULT = "x_end"

    def __init__(self, parent: QWidget = None):
        """
        QWidget to display AssayDatabaseDefinition

        Args:
            parent: QWidget parent
        """
        super().__init__(parent)

        self.layout = QGridLayout()
        self.table_cb = self._add_combobox("Table")
        self.hole_id_cb = self._add_combobox("Hole id column", self.HOLE_COL_DEFAULT)
        self.dataset_cb = self._add_combobox("Dataset column", self.DATASET_COL_DEFAULT)
        self.person_cb = self._add_combobox("Person column", self.PERSON_COL_DEFAULT)
        self.import_date_cb = self._add_combobox(
            "Import date column", self.IMPORT_DATE_COL_DEFAULT
        )
        self.x_col_cb = self._add_combobox("X column", self.X_COL_DEFAULT)
        self.x_end_col_cb = self._add_combobox("X end column", self.X_END_COL_DEFAULT)
        self.schema_cb = self._add_combobox("Schema")

        row_count = self.layout.rowCount()
        self.assay_column_definition_table = QTableView(self)
        self.assay_column_definition_table.horizontalHeader().setVisible(False)
        self.assay_column_definition_model = StringMapTableModel(
            self, "Downhole data column", "Database column"
        )
        self.assay_column_definition_table.setModel(self.assay_column_definition_model)
        self.layout.addWidget(self.assay_column_definition_table, row_count, 0, 1, 2)

        self.setLayout(self.layout)

    def set_assay_database_definition(self, assay_definition: AssayDatabaseDefinition):
        """
        Update widget with assay database definition

        Args:
            assay_definition: AssayDatabaseDefinition
        """
        self.table_cb.setCurrentText(assay_definition.table_name)
        self.hole_id_cb.setCurrentText(assay_definition.hole_id_col)
        self.dataset_cb.setCurrentText(assay_definition.dataset_col)
        self.person_cb.setCurrentText(assay_definition.person_col)
        self.import_date_cb.setCurrentText(assay_definition.import_date_col)
        self.x_col_cb.setCurrentText(assay_definition.x_col)
        self.x_end_col_cb.setCurrentText(assay_definition.x_end_col)
        self.schema_cb.setCurrentText(assay_definition.schema)

        self.assay_column_definition_model.set_string_map(assay_definition.y_col)

    def get_assay_database_definition(self) -> AssayDatabaseDefinition:
        """
        Returns current assay database definition

        Returns: AssayDatabaseDefinition

        """
        return AssayDatabaseDefinition(
            table_name=self.table_cb.currentText(),
            hole_id_col=self.hole_id_cb.currentText(),
            dataset_col=self.dataset_cb.currentText(),
            person_col=self.person_cb.currentText(),
            import_date_col=self.import_date_cb.currentText(),
            x_col=self.x_col_cb.currentText(),
            x_end_col=self.x_end_col_cb.currentText(),
            schema=self.schema_cb.currentText(),
            y_col=self.assay_column_definition_model.get_string_map(),
        )

    def _add_combobox(self, name: str, default_val: str = None) -> QComboBox:
        """
        Add combobox and label to layout and returns created combobox

        Args:
            name: label for combobox
            default_val: default value for combobox

        Returns: created QComboBox

        """
        row_count = self.layout.rowCount()
        self.layout.addWidget(QLabel(name), row_count, 0)
        cb = QComboBox()
        cb.setEditable(True)
        if default_val:
            cb.addItem(default_val)
        self.layout.addWidget(cb, row_count, 1)
        return cb
