# encoding: utf-8
#
#  Project: 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 Characterisation class.
Defines:
characterise, get_html_report methods, input_from_params, dc_from_output and
get_default_characterisation_parameters abstract methods;
prepare_input and is_running methods.
"""

import abc

import gevent.event

from mxcubecore.BaseHardwareObjects import HardwareObject


class AbstractCharacterisation(HardwareObject):
    """Abstract Characterisation Class"""

    __metaclass__ = abc.ABCMeta

    def __init__(self, name):
        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 softare.
        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'

        Args:
            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'

        Args:
          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):
        """
        Returns:
            (bool) True if process is running otherwise False
        """
        return not self.processing_done_event.is_set()
