# coding: utf-8
# /*##########################################################################
#
# Copyright (c) 2016-2017 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# ###########################################################################*/

__authors__ = ["H. Payno", ]
__license__ = "MIT"
__date__ = "06/03/2020"


from silx.gui import qt
from ..utils import WidgetLongProcessing
from Orange.widgets import widget, gui
from Orange.widgets.widget import Output
from tomwer.core.scan.scanbase import TomwerScanBase
from tomwer.core.process.datalistener import DataListener
from tomwer.utils import docstring
from tomwer.synctools.datalistener import DataListenerQThread
from tomwer.gui.control.datalistener import DataListenerWidget
from tomwer.synctools.datalistener import MockDataListenerQThread
from tomwer.web.client import OWClient
from Orange.widgets import settings
import logging

logger = logging.getLogger(__name__)


class DataListenerOW(widget.OWWidget, OWClient, WidgetLongProcessing,
                     DataListener):
    """
    This widget is used to listen to a server notifying the widget when an
    acquisition is finished.
    Then the tango file will be converted to .nx file, NXtomo compliant.
    """
    name = "data listener"
    id = "orangecontrib.widgets.tomwer.control.DataListenerOW.DataListenerOW"
    description = "The widget will listen to (hdf5) tango acquisition and " \
                  "wait for acquisition to be finished. Once finished it " \
                  "will call nxtomomill to convert from tango .hdf5 to " \
                  "NXtomo compliant .nx file"
    icon = "icons/datalistener.svg"
    priority = 2
    category = "tomwer"
    keywords = ["tomography", "file", "tomwer", "listener", "datalistener",
                "hdf5", "NXtomo"]

    allows_cycle = True
    compress_signal = False

    want_main_area = True
    resizing_enabled = True

    _blissConfiguration = settings.Setting(dict())

    class Outputs:
        data_out = Output(name='data',
                          type=TomwerScanBase,
                          doc='one scan to be process')

    def __init__(self, parent=None):
        widget.OWWidget.__init__(self, parent)
        OWClient.__init__(self, (logger, ))
        WidgetLongProcessing.__init__(self)
        DataListener.__init__(self)
        self._widget = DataListenerWidget(parent=self)
        self._mock = False

        self._box = gui.vBox(self.mainArea, self.name)
        layout = self._box.layout()
        layout.addWidget(self._widget)

        # signal / slot connection
        self._widget.sigActivate.connect(self._activated)
        self._widget.sigDeactivate.connect(self._deactivated)
        self._widget.sigConfigurationChanged.connect(self._tangoDeviceChanged)
        self._widget.sigAcquisitionEnded.connect(self._process_bliss_file_frm_tuple)

        # set up
        if self._blissConfiguration != {}:
            self._widget.setBlissServerConfiguation(self._blissConfiguration)

    def _process_bliss_file_frm_tuple(self, t):
        master_file, entry, proposal_file = t
        return self.process_bliss_file(bliss_file=master_file,
                                       entry=entry,
                                       proposal_file=proposal_file)

    def _activated(self):
        self.activate(True)

    def _deactivated(self):
        self.activate(False)

    @docstring(DataListener.activate)
    def activate(self, activate=True):
        old = self._widget.blockSignals(True)
        self.set_configuration(self._widget.getBlissServerConfiguration())
        self._widget.activate(activate=activate)
        DataListener.activate(self, activate=activate)
        self.processing_state(activate, info='listener active')
        self._widget.blockSignals(old)

    def _signal_scan_ready(self, scan):
        assert isinstance(scan, TomwerScanBase)
        self.Outputs.data_out.send(scan)

    def _ask_user_for_overwritting(self, file_path):
        msg = qt.QMessageBox(self)
        msg.setIcon(qt.QMessageBox.Question)
        types = qt.QMessageBox.Ok | qt.QMessageBox.Cancel
        msg.setStandardButtons(types)

        text = "NXtomomill will overwrite: \n %s. Do you agree ?" % file_path
        msg.setText(text)
        return msg.exec_() == qt.QMessageBox.Ok

    def _tangoDeviceChanged(self):
        self._blissConfiguration = self._widget.getBlissServerConfiguration()
        if self.is_active():
            self.activate(False)
            self.activate(True)

    def setMock(self, mock, acquisitions):
        self._mock = mock
        self._mock_acquisitions = acquisitions

    @docstring(DataListener.create_listening_thread)
    def create_listening_thread(self):
        if self._mock is True:
            thread = MockDataListenerQThread(acquisitions=None,
                                             mock_acquisitions=self._mock_acquisitions)
        else:
            thread = DataListenerQThread(device=self.session_name,
                                         acquisitions=None)
        # connect thread
        thread.sigAcquisitionStarted.connect(self._widget._acquisitionStarted)
        thread.sigAcquisitionEnded.connect(self._widget._acquisitionEnded)
        thread.sigScanAdded.connect(self._widget._acquisitionUpdated)
        return thread

    @docstring(DataListener.delete_listening_thread)
    def delete_listening_thread(self):
        self._listening_thread.sigAcquisitionStarted.disconnect(self._widget._acquisitionStarted)
        self._listening_thread.sigAcquisitionEnded.disconnect(self._widget._acquisitionEnded)
        self._listening_thread.sigScanAdded.disconnect(self._widget._acquisitionUpdated)
        DataListener.delete_listening_thread(self)

    def close(self):
        self.activate(False)
        widget.OWWidget.close(self)

    def _get_n_scan_observe(self):
        return self._widget._observationWidget.observationTable.model().rowCount()

    def _get_n_scan_finished(self):
        return self._widget._historyWindow.scanHistory.model().rowCount()
