'''
/***************************************************************************
Name          :  time_series_list_controller.py
Description   :  Time Series List
copyright     :  (C) 2019-2023 by FEWS
email         :  achristianson@contractor.usgs.gov
Created       :  02/20/2020 - ACHRISTIANSON
Modified      :  07/13/2020 - cholen - Fixed bug where file was being left open
                             applied os sep fix
                 11/04/2020 - cholen - Adjust check for missing files
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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
import re

from PyQt5.QtWidgets import QDialog, QMessageBox, QFileDialog
from qgis.core import QgsMessageLog, Qgis

from fews_tools.forms.Ui_TimeSeriesListFile import Ui_TimeSeriesListFile
from fews_tools.models.datasets_model import DatasetsModel
from fews_tools.models.workspace_setup_model import WorkspaceSetupModel

from fews_tools.utilities import geoclim_utilities as util


class TimeSeriesListController(QDialog):
    '''
    Class to list Time Series Data
    '''
    def __init__(self):
        QDialog.__init__(self)
        self.ui = Ui_TimeSeriesListFile()
        self.ui.setupUi(self)
        self.datasets_info = DatasetsModel()
        self.wrksp_setup = WorkspaceSetupModel()
        self.ds_dic = None
        self.input_files_list = []
        self.selected_files_list = []
        self.missing_files_list = []
        self.available_files_list = []
        self.beg_per = ''
        self.end_per = ''
        self.available_years_list = []
        self.main_yr_control = []
        self.selected_period_list = []
        self.selected_year_list = []
        # fill in dataset and param boxes
        util.fill_dataset_combo(self.ui.datasetComboBox)
        # make connections to methods
        self.ui.datasetComboBox.currentIndexChanged.connect(
            self.dataset_selection_changed)
        self.ui.browsePushButton.clicked.connect(self.show_browse_dialog)
        self.ui.periodPushButton.clicked[bool].connect(self.select_all_periods)
        self.ui.yearPushButton.clicked[bool].connect(self.select_all_years)
        self.ui.createListPushButton.clicked.connect(self.create_list)
        # setting param box to False, user doesn't need to change
        self.ui.parameterLineEdit.setEnabled(False)
        self.ui.outputLineEdit.setEnabled(False)
        self.ui.periodPushButton.setCheckable(True)
        self.ui.yearPushButton.setCheckable(True)
        # set default output path, user can change
        self.output_path = self.wrksp_setup.get_output_path()
        # temp path, needed for time series file save
        self.temp_path = self.wrksp_setup.get_temp_data_path()
        self.list_filename = 'tempfile.lst'
        self.ui.listNameLineEdit.setText(self.list_filename)
        # set progress bar equal to 0
        self.ui.progressBar.setValue(0)
        self.dataset_selection_changed()

    def create_list(self):
        '''
        Function to create list and write it to .lst file
        '''
        self.ui.progressBar.setValue(0)
        self.get_selected_periods()
        self.get_selected_years()
        self.ts_list_filename = self.ui.listNameLineEdit.text()
        self.output_path = self.ui.outputLineEdit.text()
        self.list_filename = os.path.join(self.ui.outputLineEdit.text(),
                                          self.ts_list_filename)

        (self.selected_files_list,
         self.available_files_list,
         self.missing_files_list) =\
            util.check_non_consecutive_process_inputs(
                self.ds_dic, self.selected_year_list,
                self.selected_period_list, False)
        # checks for missing files in selected list
        if self.missing_files_list:
            self.ui.progressBar.setValue(0)
            QMessageBox.information(self,
                                    u"Missing files!! \n",
                                    str('\n'.join(self.missing_files_list)),
                                    QMessageBox.Ok)
            QgsMessageLog.logMessage(u"Missing files!!",
                                     level=Qgis.Info)
            return
        # checks list name entry for errors
        list_name = self.ui.listNameLineEdit.text()
        pattern = r'[^_\.a-zA-Z0-9]'
        good_list_name = list_name.find('.lst')
        if len(self.ui.listNameLineEdit.text()) > 15 or\
                len(self.ui.listNameLineEdit.text()) <= 0:
            QMessageBox.information(self, 'Error!!',
                                    'List Name must be between 1 and 15 '
                                    'characters!',
                                    QMessageBox.Ok)
            return
        # checks if list name contains only alphanumeric letters
        if re.search(pattern, list_name):
            QMessageBox.information(self, 'Error!!',
                                    'List name must contain only '
                                    'alphanumeric letters!!',
                                    QMessageBox.Ok)
            return
        # checks if list name ends with .lst
        if good_list_name <= 0:
            QMessageBox.information(self, 'Error',
                                    'List name must contain .lst!!',
                                    QMessageBox.Ok)
            return
        # checks to make sure output file is selected
        if self.ui.outputLineEdit.text() == '':
            QMessageBox.information(self, 'Error!!',
                                    'Please select an output file!!',
                                    QMessageBox.Ok)
            return
        elif len(self.available_files_list) > 0:
            with open(self.list_filename, 'w') as lst_file:
                for row in self.available_files_list:
                    lst_file.write(row + '\n')
        self.ui.progressBar.setValue(100)
        self.close()

    def dataset_selection_changed(self):
        '''
        Function to update GUI widgets based on dataset selection
        '''
        self.datasets_info.query_named_dataset(
            self.ui.datasetComboBox.currentText())
        self.ds_dic = self.datasets_info.get_ds_dictionary()
        self.input_files_list = util.get_input_file_list(self.ds_dic)
        util.fill_ds_type_widget(self.ui.parameterLineEdit, self.ds_dic)
        if not self.input_files_list:
            QMessageBox.information(self,
                                    u'Data missing!!',
                                    u'No data available for dataset!!',
                                    QMessageBox.Ok)
            self.ui.periodListWidget.clear()
            self.ui.yearListWidget.clear()
            self.ui.parameterLineEdit.clear()
            return
        self.beg_per = util.extract_data_period(
            self.ds_dic, self.input_files_list[0])
        self.end_per = util.extract_data_period(
            self.ds_dic, self.input_files_list[-1])
        self.available_years_list =\
            util.extract_data_years(self.ds_dic, self.input_files_list)
        self.update_year_period_list()

    def get_file_information(self):
        '''
        Function to get file information
        '''
        return self.list_filename

    def get_selected_file_list(self):
        '''
        Function to selected file list
        '''
        return self.selected_files_list

    def get_selected_periods(self):
        '''
        Function to get selected periods from GUI
        '''
        self.selected_period_list = self.ui.periodListWidget.selectedItems()
        self.selected_period_list = util.convert_gui_periods_to_file_periods(
            self.ui.periodListWidget, self.ds_dic)
        if self.ui.periodListWidget.selectedItems() == []:
            QMessageBox.information(self, 'Error!!',
                                    'Please select periods to analyze!!',
                                    QMessageBox.Ok)
            return
        return self.selected_period_list

    def get_selected_years(self):
        '''
        Function to get selected years from GUI
        '''
        selected_year_list = self.ui.yearListWidget.selectedItems()
        if self.ui.yearListWidget.selectedItems() == []:
            QMessageBox.information(self, 'Error!!',
                                    'Please select years to analyze!!',
                                    QMessageBox.Ok)
            return
        for item in selected_year_list:
            self.selected_year_list.append(item.text())
        self.selected_year_list = sorted(set(self.selected_year_list))

    def select_all_periods(self, pressed):
        '''
        Function to select/deselect all periods
        params(boolean) - pressed - State of the periods push button.
        '''
        source = self.sender()
        if pressed:
            source.setText(u'Clear All Periods')
            self.ui.periodListWidget.selectAll()
        else:
            source.setText(u'Select All Periods')
            self.ui.periodListWidget.clearSelection()
        self.ui.progressBar.setValue(0)

    def select_all_years(self, pressed):
        '''
        Function to select/deselect all years
        params(boolean) - pressed - State of years push button.
        '''
        source = self.sender()
        if pressed:
            source.setText(u'Clear All Years')
            self.ui.yearListWidget.selectAll()
        else:
            source.setText(u'Select All Years')
            self.ui.yearListWidget.clearSelection()
        self.ui.progressBar.setValue(0)

    def show_browse_dialog(self):
        '''
        Function to browse/save output for time series to directory
        '''
        f_name =\
            QFileDialog.getExistingDirectory(None,
                                             u'Select Output Directory',
                                             self.wrksp_setup.get_workspace())
        if f_name:
            file_path = self.wrksp_setup.fix_os_sep_in_path(f_name)
            self.ui.outputLineEdit.setText(file_path)

    def update_year_period_list(self):
        '''
        Function to update year/period list when dataset is changed
        '''
        mid_point = util.get_midpoint(self.ds_dic)
        self.main_yr_control = util.fill_year_widget(self.ui.yearListWidget,
                                                     False,
                                                     self.available_years_list,
                                                     self.beg_per,
                                                     self.end_per,
                                                     mid_point)
        # handles periods
        util.fill_period_widget(self.ui.periodListWidget, False, self.ds_dic['PERIODICITY'])
