"""Grey Level analysis, applied to correction of flicker in image series."""


# Nonstandard imports
import numpy as np

# Local imports
from .grey_level import GreyLevel, GreyLevelViewer
from .grey_level import GreyLevelFormatter_Pandas, GreyLevelResults_PandasTsv


class FlickerViewer(GreyLevelViewer):
    pass


class FlickerFormatter_Pandas(GreyLevelFormatter_Pandas):

    def _to_pandas(self):
        """How to convert data generated by _store_data() into a pandas table."""
        data_table = super()._to_pandas()
        data_table['ratio'] = data_table.filter(like='zone').mean(axis=1)
        return data_table


class FlickerResults_PandasTsv(GreyLevelResults_PandasTsv):

    measurement_type = 'flicker'
    default_filename = 'Img_Flicker'


class Flicker(GreyLevel):
    """Class to perform analysis of flicker on image series

    (based on Grey Level analysis)
    """

    measurement_type = 'flicker'

    DefaultViewer = FlickerViewer
    DefaultFormatter = FlickerFormatter_Pandas
    DefaultResults = FlickerResults_PandasTsv

    def __init__(
        self,
        img_series,
        savepath=None,
        reference=0,
        func=np.mean,
        Viewer=None,
        Formatter=None,
        Results=None,
    ):
        """Analysis of avg gray level on selected zone in series of images.

        Parameters
        ----------
        - img_series: image series from the ImgSeries class or subclasses

        - savepath: folder in which to save analysis data & metadata
                    (if not specified, the img_series savepath is used)

        - reference: num of image which will serve to normalize others.

        - func: function to be applied on the image pixels in the defined
                analysis zones (default: np.mean). Other typical functions
                can be: np.sum, np.max, etc.

        - Viewer: Viewer class/subclasses that is used to display and inspect
                  analysis data (is used by ViewerTools)
                  (if not specified, use default Viewer)

        - Formatter: class/subclass of Formatter to format results spit out
                     by the raw analysis into something storable/saveable
                     by the Results class.
                     (if not specified, use default Formatter)

        - Results: Results class/subclasses that is used to store, save and
                   load analysis data and metadata.
                   (if not specified, use default Results)
        """
        super().__init__(
            img_series=img_series,
            savepath=savepath,
            Viewer=Viewer,
            Formatter=Formatter,
            Results=Results,
            func=func,
        )
        self.reference = reference

    def _initialize(self):
        """Check everything OK before starting analysis & initialize params."""
        super()._initialize()
        self.ref_values = None
        data = self.analyze(num=self.reference, live=False)
        self.ref_values = data['glevels']

    def _analyze(self, img):
        """Basic analysis function, to be threaded or multiprocessed.

        Parameters
        ----------
        - img: image array to be analyzed (e.g. numpy array).

        Output
        ------
        - data, handled by self.formatter._store_data()
        """
        data = super()._analyze(img)
        glevels = data['glevels']
        if self.ref_values is not None:
            # Only useful to define reference values upon __init__()
            data['glevels'] = [
                glevel / ref_val for glevel, ref_val in zip(glevels, self.ref_values)
            ]
        return data
