# 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.


import ocw.utils as utils
import numpy as np
from scipy.stats import percentileofscore, linregress


class Downscaling:

    def __init__(self, ref_dataset, model_present, model_future):
        '''
        :param ref_dataset: The Dataset to use as the reference dataset (observation)
        :type ref_dataset: Dataset
        :param model_present: model simulation to be compared with observation
        :type model_present: Dataset
        :param model_future: model simulation to be calibrated for prediction
        :type model_future: Dataset
        '''
        self.ref_dataset = ref_dataset[~ref_dataset.mask].ravel()
        self.model_present = model_present.ravel()
        self.model_future = model_future.ravel()

    description = "statistical downscaling methods"

    def Delta_addition(self):
        '''Calculate the mean difference between future and present simulation, 
           then add the difference to the observed distribution

        :returns: downscaled model_present and model_future
        '''
        ref = self.ref_dataset
        model_present = self.model_present
        model_future = self.model_future

        return model_present, ref + np.mean(model_future - model_present)

    def Delta_correction(self):
        '''Calculate the mean difference between observation and present simulation,
           then add the difference to the future distribution

        :returns: downscaled model_present and model_future
        '''
        ref = self.ref_dataset
        model_present = self.model_present
        model_future = self.model_future

        return model_present + np.mean(ref) - np.mean(model_present), model_future + np.mean(ref) - np.mean(model_present)

    def Quantile_mapping(self):
        '''Remove the biases for each quantile value 
        Wood et al (2004) HYDROLOGIC IMPLICATIONS OF DYNAMICAL AND STATISTICAL APPROACHES TO DOWNSCALING CLIMATE MODEL OUTPUTS

        :returns: downscaled model_present and model_future
        '''
        ref = self.ref_dataset
        model_present = self.model_present
        model_present_corrected = np.zeros(model_present.size)
        model_future = self.model_future
        model_future_corrected = np.zeros(model_future.size)

        for ival, model_value in enumerate(model_present):
            percentile = percentileofscore(model_present, model_value)
            model_present_corrected[ival] = np.percentile(ref, percentile)

        for ival, model_value in enumerate(model_future):
            percentile = percentileofscore(model_future, model_value)
            model_future_corrected[ival] = model_value + np.percentile(
                ref, percentile) - np.percentile(model_present, percentile)

        return model_present_corrected, model_future_corrected

    def Asynchronous_regression(self):
        '''Remove the biases by fitting a linear regression model with ordered observational and model datasets
        Stoner et al (2013) An asynchronous regional regression model for statistical downscaling of daily climate variables    

        :returns: downscaled model_present and model_future
        '''

        ref_original = self.ref_dataset
        model_present = self.model_present
        model_present_sorted = np.sort(model_present)
        model_future = self.model_future

        # For linear regression, the size of reference data must be same as
        # model data.
        ref = np.zeros(model_present.size)

        for ival, model_value in enumerate(model_present_sorted):
            percentile = percentileofscore(model_present_sorted, model_value)
            ref[ival] = np.percentile(ref_original, percentile)

        slope, intercept = linregress(model_present_sorted, ref)[0:2]

        return model_present * slope + intercept, model_future * slope + intercept
