# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

'''
Classes:
    Metric - Abstract Base Class from which all metrics must inherit.
'''

from abc import ABCMeta, abstractmethod
import ocw.utils as utils
import numpy
from scipy import stats

class Metric(object):
    '''Base Metric Class'''
    __metaclass__ = ABCMeta


class UnaryMetric(Metric):
    '''Abstract Base Class from which all unary metrics inherit.'''
    __metaclass__ = ABCMeta

    @abstractmethod
    def run(self, target_dataset):
        '''Run the metric for a given target dataset.

        :param target_dataset: The dataset on which the current metric will
            be run.

        :returns: The result of evaluating the metric on the target_dataset.
        '''


class BinaryMetric(Metric):
    '''Abstract Base Class from which all binary metrics inherit.'''
    __metaclass__ = ABCMeta

    @abstractmethod
    def run(self, ref_dataset, target_dataset):
        '''Run the metric for the given reference and target datasets.

        :param ref_dataset: The Dataset to use as the reference dataset when
            running the evaluation.
        :type ref_dataset: Dataset
        :param target_dataset: The Dataset to use as the target dataset when
            running the evaluation.

        :returns: The result of evaluation the metric on the reference and 
            target dataset.
        '''


class Bias(BinaryMetric):
    '''Calculate the bias between a reference and target dataset.'''

    def run(self, ref_dataset, target_dataset):
        '''Calculate the bias between a reference and target dataset.

        .. note::
           Overrides BinaryMetric.run()

        :param ref_dataset: The reference dataset to use in this metric run.
        :type ref_dataset: Dataset.
        :param target_dataset: The target dataset to evaluate against the
            reference dataset in this metric run.
        :type target_dataset: Dataset.

        :returns: The difference between the reference and target datasets.
        :rtype: Numpy Array
        '''
        return ref_dataset.values - target_dataset.values


class TemporalStdDev(UnaryMetric):
    '''Calculate the standard deviation over the time.'''

    def run(self, target_dataset):
        '''Calculate the temporal std. dev. for a datasets.

        .. note::
           Overrides UnaryMetric.run()

        :param target_dataset: The target_dataset on which to calculate the 
            temporal standard deviation.
        :type target_dataset: Dataset

        :returns: The temporal standard deviation of the target dataset
        :rtype: Numpy Array
        '''
        return target_dataset.values.std(axis=0, ddof=1)


class SpatialStdDevRatio(BinaryMetric):
    '''Calculate the ratio of spatial standard deviation (model standard
          deviation)/(observed standard deviation)'''

    def run(self, ref_dataset, target_dataset):
        '''Calculate the ratio of spatial std. dev. between a reference and
            target dataset.

        .. note::
           Overrides BinaryMetric.run()

        :param ref_dataset: The reference dataset to use in this metric run.
        :type ref_dataset: Dataset.
        :param target_dataset: The target dataset to evaluate against the
            reference dataset in this metric run.
        :type target_dataset: Dataset.

        :returns: The ratio of standard deviation of the reference and target
            dataset.
        '''

        # This is calcClimYear function for ref_dataset
        reshaped_ref_data = utils.reshape_monthly_to_annually(ref_dataset)
        ref_t_series = reshaped_ref_data.mean(axis=1)
        ref_means = ref_t_series.mean(axis=0)

        # This is calcClimYear function for target_dataset
        reshaped_target_data = utils.reshape_monthly_to_annually(target_dataset)
        target_t_series = reshaped_target_data.mean(axis=1)
        target_means = target_t_series.mean(axis=0)

        return numpy.std(ref_means) / numpy.std(target_means)


class PatternCorrelation(BinaryMetric):
    '''Calculate the spatial correlation'''

    def run(self, ref_dataset, target_dataset):
        '''Calculate the spatial correlation between a reference and target dataset.
            Using: scipy.stats.pearsonr

        .. note::
           Overrides BinaryMetric.run()

        :param ref_dataset: The reference dataset to use in this metric run.
        :type ref_dataset: Dataset.
        :param target_dataset: The target dataset to evaluate against the
            reference dataset in this metric run.
        :type target_dataset: Dataset.

        :returns: The spatial correlation between a reference and target dataset.
        '''
        # This is calcClimYear function for ref_dataset
        reshaped_ref_data = utils.reshape_monthly_to_annually(ref_dataset)
        ref_t_series = reshaped_ref_data.mean(axis=1)
        ref_means = ref_t_series.mean(axis=0)

        # This is calcClimYear function for target_dataset
        reshaped_target_data = utils.reshape_monthly_to_annually(target_dataset)
        target_t_series = reshaped_target_data.mean(axis=1)
        target_means = target_t_series.mean(axis=0)

        pattern_correlation, p_value = stats.pearsonr(target_means.flatten(),ref_means.flatten())
        return pattern_correlation, p_value


