# encoding: utf-8
#
#  Project name: MXCuBE
#  https://github.com/mxcube
#
#  This file is part of MXCuBE software.
#
#  MXCuBE is free software: you can redistribute it and/or modify
#  it under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  MXCuBE is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Lesser General Public License for more details.
#
#  You should have received a copy of the GNU General Lesser Public License
#  along with MXCuBE. If not, see <http://www.gnu.org/licenses/>.

"""Abstract hardware object class for characterisation."""

import abc

import gevent.event

from mxcubecore.BaseHardwareObjects import HardwareObject


class AbstractCharacterisation(HardwareObject):
    """Abstract hardware object class for characterisation."""

    __metaclass__ = abc.ABCMeta

    def __init__(self, name) -> None:
        super().__init__(name)
        self.processing_done_event = gevent.event.Event()

    @abc.abstractmethod
    def characterise(self, _input):
        """Start the characterosation.

        Args:
            input (object): Characterisation input object.

        Returns:
            (str) The Characterisation result.
        """

    @abc.abstractmethod
    def get_html_report(self, output):
        """Get the path to the characterisation html report, generated by the
        characterisation software.

        Args:
            output (object): Characterisation output object

        Returns:
            (str) The path to the html result report.
        """

    @abc.abstractmethod
    def input_from_params(self, ref_parameters, char_params, path_str):
        """
        Args:
            ref_parameters:
                A named tuple or object with following fields:

                'id',
                'prefix',
                'run_number',
                'template',
                'first_image',
                'num_images',
                'osc_start',
                'osc_range',
                'overlap',
                'exp_time',
                'num_passes',
                'comments',
                'path',
                'centred_positions',
                'energy',
                'resolution',
                'transmission',
                'shutterless',
                'inverse_beam',
                'screening_id'

            char_params:
                A named tuple or object with following fields:

                # Optimisation parameters
                'aimed_resolution'
                'aimed_multiplicity'
                'aimed_i_sigma'
                'aimed_completness'
                'strategy_complexity'
                'induce_burn'
                'use_permitted_rotation'
                'permitted_phi_start'
                'permitted_phi_end'

                # Crystal
                'max_crystal_vdim'
                'min_crystal_vdim'
                'max_crystal_vphi'
                'min_crystal_vphi'
                'space_group'

                # Characterisation type
                'use_min_dose'
                'use_min_time'
                'min_dose'
                'min_time'
                'account_rad_damage'
                'not_use_low_res'
                'auto_res'
                'opt_sad'
                'sad_res'
                'determine_rad_params'

                # Radiation damage model
                'rad_suscept'
                'beta'
                'sigma'

            path_str: Template string representing path to each image.

        Returns:
            Input for characterisation software.
        """

    @abc.abstractmethod
    def dc_from_output(self, output):
        """Create a data collection from characterisation result

        Args:
            output (object): Characterisation result object

        Returns:
            (queue_model_objects.DataCollection)
        """

    @abc.abstractmethod
    def get_default_characterisation_parameters(self, default_input_file):
        """
        Args:
            default_input_file (str): Path to file containing default input.

        Returns:
            (queue_model_objects.CharacterisationsParameters): object with
            default parameters.
        """

    def prepare_input(self, _input):
        """Called by characterise before characterisation starts.

        Can be used to manipulate edna_input object before characterisation starts.
        Example: to set a site specific output directory

        Args:
           _input (object): Characterisation input object.
        """

    def is_running(self) -> bool:
        """
        Returns:
            ``True`` if process is running otherwise ``False``.
        """
        return not self.processing_done_event.is_set()
