"""
/***************************************************************************
Name            :  rainfall_summary_worker.py
Description     :  A class used to handle the back-end behavior
copyright       :  (C) 2019-2023 by FEWS
email           :  minxuansun@contractor.usgs.gov
Created         :  01/22/2020 Minxuan Sun
Modified        :  07/14/2020 cholen - Adjust error
                   11/03/2020 cholen - Resample inputs
                   01/05/2022 cholen - SCA cleanup add gdal utilities
                   06/23/2022 cholen - Fix path for region mask file
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/
"""

import os

from PyQt5 import QtCore

from qgis.core import QgsMessageLog, Qgis

from fews_tools.utilities import geoclim_gdal_utilities as g_util


class RainfallSummaryWorker(QtCore.QObject):
    """
    Rainfall Summary worker class
    """
    def __init__(self, workspace, dataset_dic, region_dic, sum_file_path,
                 average_file_path, difference_file_path, percentage_file_path,
                 data_file_list, average_file_list):
        QtCore.QObject.__init__(self)
        self.wrksp_setup = workspace
        self.ds_dic = dataset_dic
        self.reg_dic = region_dic
        self.sum_output_filename = sum_file_path
        self.average_output_filename = average_file_path
        self.difference_output_filename = difference_file_path
        self.percent_output_filename = percentage_file_path
        self.data_file_list = data_file_list
        self.average_file_list = average_file_list
        self.killed = False
        self.step = 0.0
        self.curr_progress = 0.0

        self.output_path = os.path.split(self.sum_output_filename)[0]
        self.mask_file, _ = g_util.resample_input_files(
            self.output_path, self.reg_dic['Mask'], [], self.reg_dic)

    def kill(self):
        """
        set kill flog to true to stop processing.
        """
        self.killed = True

    def update_progress(self):
        '''
        Helper for progress bar updates
        '''
        self.curr_progress += self.step
        if self.curr_progress > 90:
            self.curr_progress = 90
        self.progress.emit(int(self.curr_progress))

    def run(self):
        """
        Call calculation functions here to generate output raster.
        """
        ret_tuple = None
        try:
            QgsMessageLog.logMessage(u"Begin generating rainfall summaries",
                                     level=Qgis.Info)
            # put rainfall summaries algorithm here
            # figure progress step for bar
            self.step = \
                90.0 / 6.0
            self.curr_progress = 0
            _, resamp_data_list =\
                g_util.resample_input_files(
                    self.output_path, None,
                    self.data_file_list, self.reg_dic)
            # don't trust the files' nodata, sometimes data providers don't
            # use it or in the case of CHIRPS have it set to the wrong value
            # always use the GUI specified value
            _, row_ct, col_ct, geoxform, txt_data_type =\
                g_util.get_geotiff_info(resamp_data_list[0])
            np_data_type = g_util.TYPE_DIC[txt_data_type]["NP"]
            gd_data_type = g_util.TYPE_DIC[txt_data_type]["GDAL"]
            if self.killed is True:
                raise KeyboardInterrupt
            # build the data cube
            data_cube = g_util.get_data_cube(resamp_data_list, np_data_type)
            self.update_progress()
            # build the mask
            full_mask_array = g_util.get_data_cube_and_region_mask(
                data_cube, self.mask_file, self.ds_dic['DATAMISSINGVALUE'])
            self.update_progress()

            # sum and mask the data_cube
            masked_sum_array = g_util.calc_masked_data_cube_sum(
                data_cube, full_mask_array,
                self.ds_dic['DATAMISSINGVALUE'])
            err = g_util.write_file(
                self.sum_output_filename,
                masked_sum_array,
                col_ct, row_ct,
                geoxform,
                gd_data_type)
            if self.killed is True:
                raise KeyboardInterrupt
            if err is True:
                raise RuntimeError
            QgsMessageLog.logMessage("Data files sum complete",
                                     level=Qgis.Info)
            self.update_progress()

            # sum and mask the average data_cube
            _, resamp_avg_list =\
                g_util.resample_input_files(
                    self.output_path, None,
                    self.average_file_list, self.reg_dic)
            avg_data_cube = g_util.get_data_cube(resamp_avg_list, np_data_type)
            avg_mask_array = g_util.get_data_cube_and_region_mask(
                avg_data_cube, self.mask_file, self.ds_dic['DATAMISSINGVALUE'])

            masked_avg_sum_array = g_util.calc_masked_data_cube_sum(
                avg_data_cube, avg_mask_array,
                self.ds_dic['DATAMISSINGVALUE'])
            err = g_util.write_file(
                self.average_output_filename,
                masked_avg_sum_array,
                col_ct, row_ct,
                geoxform,
                gd_data_type)
            if self.killed is True:
                raise KeyboardInterrupt
            if err is True:
                raise RuntimeError
            QgsMessageLog.logMessage("Average files sum complete",
                                     level=Qgis.Info)
            self.update_progress()

            # create the difference file
            masked_diff_array = g_util.calc_masked_array_diff(
                masked_sum_array, masked_avg_sum_array,
                full_mask_array, self.ds_dic['DATAMISSINGVALUE'])
            err = g_util.write_file(
                self.difference_output_filename,
                masked_diff_array,
                col_ct, row_ct,
                geoxform,
                gd_data_type)
            if self.killed is True:
                raise KeyboardInterrupt
            if err is True:
                raise RuntimeError
            QgsMessageLog.logMessage("Datas sum - average sum complete",
                                     level=Qgis.Info)
            self.update_progress()

            # create the percentage file
            masked_pct_of_avg_array = g_util.calc_masked_pct_of_avg(
                masked_sum_array, masked_avg_sum_array,
                full_mask_array, self.ds_dic['DATAMISSINGVALUE'])
            err = g_util.write_file(
                self.percent_output_filename,
                masked_pct_of_avg_array,
                col_ct, row_ct,
                geoxform,
                g_util.TYPE_DIC["Int32"]["GDAL"])
            if self.killed is True:
                raise KeyboardInterrupt
            if err is True:
                raise RuntimeError
            self.update_progress()
            QgsMessageLog.logMessage("Data sum /avg sum % complete",
                                     level=Qgis.Info)
            # set these to none or the temp removal in the controller will fail
           #  self.mask_file = None

            if self.killed is False:
                self.progress.emit(100)
                ret_tuple = (0, u"Rainfall summaries complete")
        # exit with appropriate message on killed (KeyboardInterrupt)
        except KeyboardInterrupt:
            self.progress.emit(0)
            ret_tuple = (0, u"Rainfall summaries aborted by user")
        # forward any execeptions upstream
        except BaseException as exc:
            self.error.emit(exc, u"Unspecified error in Rainfall Summaries")
        self.finished.emit(ret_tuple)

    finished = QtCore.pyqtSignal(object)

    error = QtCore.pyqtSignal(Exception, str)

    progress = QtCore.pyqtSignal(int)
    