#!/usr/bin/env python
"""
Initialization of the step6
"""

import matplotlib
import numpy as np

matplotlib.use("Qt5Agg")
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from qtpy.QtWidgets import QVBoxLayout

from ibeatles import ANGSTROMS, LAMBDA, SUB_0, DataType
from ibeatles.fitting import FittingTabSelected
from ibeatles.fitting.kropff import BraggPeakInitParameters
from ibeatles.session import SessionKeys, SessionSubKeys
from ibeatles.step6 import (
    CMAPS,
    DEFAULT_CMAP_INDEX,
    DEFAULT_INTERPOLATION_INDEX,
    INTERPOLATION_METHODS,
    ParametersToDisplay,
)
from ibeatles.step6.get import Get
from ibeatles.utilities.mplcanvas import MplCanvasColorbar
from ibeatles.widgets.qrangeslider import QRangeSlider


class Initialization:
    def __init__(self, parent=None, grand_parent=None):
        self.parent = parent
        self.grand_parent = grand_parent

    def all(self):
        self.labels()
        self.parameters()
        # self.pyqtgraph()
        self.matplotlib()
        self.data()
        self.combobox()

    def combobox(self):
        self.parent.ui.interpolation_comboBox.blockSignals(True)
        self.parent.ui.interpolation_comboBox.addItems(INTERPOLATION_METHODS)
        self.parent.ui.interpolation_comboBox.setCurrentIndex(DEFAULT_INTERPOLATION_INDEX)
        self.parent.ui.interpolation_comboBox.blockSignals(False)
        self.parent.ui.interpolation_groupBox.setVisible(True)

        self.parent.ui.cmap_comboBox.blockSignals(True)
        self.parent.ui.cmap_comboBox.addItems(CMAPS)
        self.parent.ui.cmap_comboBox.setCurrentIndex(DEFAULT_CMAP_INDEX)
        self.parent.ui.cmap_comboBox.blockSignals(False)

    def labels(self):
        self.parent.ui.range_selected_from_units_label.setText(ANGSTROMS)
        self.parent.ui.range_selected_to_units_label.setText(ANGSTROMS)
        self.parent.ui.d0_units1_label.setText(ANGSTROMS)
        self.parent.ui.d0_units2_label.setText(ANGSTROMS)
        self.parent.ui.reference_material_lambda0_units_label.setText(ANGSTROMS)
        self.parent.ui.reference_material_lambda0_label.setText(LAMBDA + SUB_0)

    def range_slider(self):
        layout = QVBoxLayout()
        self.parent.ui.range_slider = QRangeSlider(splitterWidth=100, vertical=True, min_at_the_bottom=True)

        self.parent.ui.range_slider.setMin(self.parent.slider_min)
        self.parent.ui.range_slider.setMax(self.parent.slider_max)

        o_get = Get(parent=self.parent)
        parameter_displayed = o_get.parameter_to_display()

        real_min = self.parent.min_max[parameter_displayed]["min"]
        real_max = self.parent.min_max[parameter_displayed]["max"]

        self.parent.ui.max_range_lineEdit.setText(f"{real_max:.5f}")
        self.parent.ui.min_range_lineEdit.setText(f"{real_min:.5f}")

        self.parent.ui.range_slider.setRealMin(real_min)
        self.parent.ui.range_slider.setRealMax(real_max)

        self.parent.ui.range_slider.setRealRange(real_min + 1e-10, real_max)  # trick to display full range #BUG

        self.parent.ui.range_slider.startValueChanged.connect(self.parent.range_slider_start_value_changed)
        self.parent.ui.range_slider.endValueChanged.connect(self.parent.range_slider_end_value_changed)

        layout.addWidget(self.parent.ui.range_slider)
        self.parent.ui.vertical_range_slider_widget.setLayout(layout)

        self.parent.ui.range_slider.setBackgroundStyle(
            "background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #ddd, stop:1 #333);"
        )
        self.parent.ui.range_slider.handle.setStyleSheet(
            "background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #282, stop:1 #222);"
        )

    def parameters(self):
        from_lambda = self.grand_parent.session_dict[DataType.fitting][FittingTabSelected.kropff][
            BraggPeakInitParameters.from_lambda
        ]
        to_lambda = self.grand_parent.session_dict[DataType.fitting][FittingTabSelected.kropff][
            BraggPeakInitParameters.to_lambda
        ]
        hkl_selected = self.grand_parent.session_dict[DataType.fitting][FittingTabSelected.kropff][
            BraggPeakInitParameters.hkl_selected
        ]
        lambda_0 = self.grand_parent.session_dict[DataType.fitting][FittingTabSelected.kropff][
            BraggPeakInitParameters.lambda_0
        ]
        element = self.grand_parent.session_dict[DataType.fitting][FittingTabSelected.kropff][
            BraggPeakInitParameters.element
        ]

        self.parent.ui.from_lambda.setText(from_lambda)
        self.parent.ui.to_lambda.setText(to_lambda)
        self.parent.ui.hkl_value.setText(hkl_selected)
        self.parent.ui.d0_value.setText("{:04.4f}".format(lambda_0 / 2.0))
        self.parent.ui.material_name.setText(element)
        self.parent.ui.lambda_0.setText("{:04.4f}".format(lambda_0))
        self.parent.ui.d0_user_value.setText("{:04.4f}".format(lambda_0 / 2.0))

        self.parent.bin_size = self.grand_parent.session_dict[SessionKeys.bin][SessionSubKeys.bin_size]

    def data(self):
        live_data = self.grand_parent.data_metadata[DataType.normalized]["data"]
        integrated_image = np.mean(live_data, 0)
        self.parent.integrated_image = np.transpose(integrated_image)
        [self.parent.image_size["height"], self.parent.image_size["width"]] = np.shape(integrated_image)

    # def pyqtgraph(self):
    #     image_view = pg.ImageView(view=pg.PlotItem())
    #     image_view.ui.roiBtn.hide()
    #     image_view.ui.menuBtn.hide()
    #     self.parent.image_view = image_view

    def matplotlib(self):
        def _matplotlib(parent=None, widget=None):
            sc = MplCanvasColorbar(parent, width=5, height=2, dpi=100)
            # sc.axes.plot([0,1,2,3,4,5], [10, 1, 20 ,3, 40, 50])
            toolbar = NavigationToolbar(sc, parent)
            layout = QVBoxLayout()
            layout.addWidget(toolbar)
            layout.addWidget(sc)
            widget.setLayout(layout)
            return sc

        self.parent.matplotlib_plot = _matplotlib(parent=self.parent, widget=self.parent.ui.matplotlib_widget)

        self.parent.matplotlib_interpolation_plot = _matplotlib(
            parent=self.parent, widget=self.parent.ui.matplotlib_interpolation_widget
        )

    def min_max_values(self):
        [_, x0, y0, width, height, bin_size] = self.grand_parent.session_dict[DataType.bin][SessionSubKeys.roi]

        max_row_index = self.grand_parent.session_dict[SessionKeys.bin][SessionSubKeys.nbr_row]
        max_col_index = self.grand_parent.session_dict[SessionKeys.bin][SessionSubKeys.nbr_column]

        d_array = self.parent.d_array
        d_array_roi = d_array[y0 : y0 + (max_row_index * bin_size), x0 : x0 + (max_col_index * bin_size)]
        self.parent.min_max[ParametersToDisplay.d] = {
            "min": np.nanmin(d_array_roi),
            "max": np.nanmax(d_array_roi),
            "global_min": np.nanmin(d_array_roi),
            "global_max": np.nanmax(d_array_roi),
        }

        # self.parent.min_max[ParametersToDisplay.d] = {'min': np.min(d_array_roi),
        #                                               'max': np.max(d_array_roi),
        #                                               'global_min': np.min(d_array),
        #                                               'global_max': np.max(d_array)}

        o_get = Get(parent=self.parent)
        strain_mapping = o_get.strain_mapping()
        strain_mapping_roi = strain_mapping[y0 : y0 + (max_row_index * bin_size), x0 : x0 + (max_col_index * bin_size)]
        self.parent.min_max[ParametersToDisplay.strain_mapping] = {
            "min": np.nanmin(strain_mapping_roi),
            "max": np.nanmax(strain_mapping_roi),
            "global_min": np.nanmin(strain_mapping_roi),
            "global_max": np.nanmax(strain_mapping_roi),
        }

        # self.parent.min_max[ParametersToDisplay.strain_mapping] = {'min': np.min(strain_mapping_roi),
        #                                                            'max': np.max(strain_mapping_roi),
        #                                                            'global_min': np.min(strain_mapping),
        #                                                            'global_max': np.max(strain_mapping)}
