# Copyright (c) 2011-2014, B.I.Stepanov Institute of Physics, National Academy
# of Sciences of Belarus.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program 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 General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

from PyQt4.QtCore import *
from PyQt4.QtGui import *

from common.utils import txt

from common.ParamsCollection import *
from common.ParamsDialog import *

__all__ = ['RamanPerturbanceParams', 'RamanPerturbanceParamsDialog']

# *****************************************************************************
class RamanPerturbanceParams(ParamsCollection):
    """Parameters for the procedure of estimating stability to perturbances in
    input data of the aerosol backscatter and lidar ratio retrieval algorithm
    utilizing Raman lidar signals."""

    # ---- Class attributes ---------------------------------------------------
    parameterList = [
        # ---- Global switch ----
        ParameterInfo('Global_switch', '&Enable perturbance analysis',
            'perturbanceEnabled', bool, False),

        # ---- Number of evaluations ----
        ParameterInfo('Number_of_evaluations', 'm =',
            'evaluations', int, 5, minValue = 1),

        # ---- White noise ----
        ParameterHeader('White_noise', 'Amplitude:'),
        ParameterInfo('White_noise', 'e<sub>355</sub> =',
            'whiteNoise355', float, 0.2, minValue = 0.0),
        ParameterInfo('White_noise', 'e<sub>387</sub> =',
            'whiteNoise387', float, 0.2, minValue = 0.0),
        ParameterInfo('White_noise', 'e<sub>532</sub> =',
            'whiteNoise532', float, 0.2, minValue = 0.0),
        ParameterInfo('White_noise', 'e<sub>607</sub> =',
            'whiteNoise607', float, 0.2, minValue = 0.0),
        ParameterHeader('White_noise', 'Common amplitude:'),
        ParameterInfo('White_noise', 'b =',
            'whiteNoiseCommon', float, 1.0, minValue = 0.0),

        # ---- Linear perturbance -----
        ParameterHeader('Linear_perturbance', 'Linear factor:'),
        ParameterInfo('Linear_perturbance', 'k<sub>355</sub> =',
            'linear355', float, 0.2, minValue = 0.0),
        ParameterInfo('Linear_perturbance', 'k<sub>387</sub> =',
            'linear387', float, 0.2, minValue = 0.0),
        ParameterInfo('Linear_perturbance', 'k<sub>532</sub> =',
            'linear532', float, 0.2, minValue = 0.0),
        ParameterInfo('Linear_perturbance', 'k<sub>607</sub> =',
            'linear607', float, 0.2, minValue = 0.0),
        ParameterHeader('Linear_perturbance', 'Common linear factor:'),
        ParameterInfo('Linear_perturbance', 'a =',
            'linearCommon', float, 1.0, minValue = 0.0),
    ]

    # ---- Public overridden methods ------------------------------------------
    @classmethod
    def getParameterList(cls):
        return cls.parameterList

    @classmethod
    def getSettingsFilePath(cls):
        return 'settings/RamanPerturbanceParams.ini'

# *****************************************************************************
class RamanPerturbanceParamsDialog(ParamsDialog):
    """Dialog for interactive modification of a 'RamanPerturbanceParams'
    instance."""

    # ---- Private overridden methods -----------------------------------------
    @classmethod
    def getGroupInfoList(cls):

        return [
            ParameterGroupInfo('Global_switch', ''),

            ParameterGroupInfo('Number_of_evaluations',
                '&Number of evaluations'),
            ParameterGroupInfo('White_noise', '&White noise'),

            ParameterGroupInfo('Linear_perturbance',
                '&Linear perturbance', True),
        ]

    @classmethod
    def getWindowTitle(cls):
        return 'Raman perturbance options'

    # ---- Private overridden methods -----------------------------------------
    def updateEditEnableStatus(self):
        """Disable parameter editing if 'perturbanceEnabled' is 'False'."""

        isPerturbanceEnabled = self.getValue('perturbanceEnabled')

        for attributeName in self.editWidgets:
            if attributeName != 'perturbanceEnabled':
                self.setEnabled(attributeName, isPerturbanceEnabled)

    def updateCustomErrorMessages(self):

        self.updateFactorOverflowMessages('linear', 'linearCommon', 'a')

    # ---- Private methods ----------------------------------------------------
    def updateFactorOverflowMessages(self, specificAttrPrefix, commonAttrName,
        commonDisplayName):
        """Check if parameters starting with 'specificAttrPrefix' are smaller
        than 1.0 when multiplied by the given common factor parameter, and set
        the error messages appropriately if they aren't."""

        commonValue = self.getValue(commonAttrName)
        if commonValue is None:
            return

        for attributeName in self.editWidgets:
            # Don't check the value of the common factor itself.
            if (attributeName.startswith(specificAttrPrefix) and
                attributeName != commonAttrName):

                specificValue = self.getValue(attributeName)

                if (specificValue is not None and
                    specificValue * commonValue >= 1.0):
                    self.setErrorMessage(attributeName,
                        'This value, when multiplied by the common factor %s, '
                        'must be smaller than 1' %
                        txt.quote(commonDisplayName, addQuotes = False))
