import glob
import os
import subprocess
import time

from crossnetwork_processing_functions import set_file_permissions_ownership, create_GHOST_stage_logfile
from GHOST_standards import standard_temporal_resolutions

class StationAggregate:

    '''Class which aggregates all station data of a defined temporal resolution, for a defined yearmonth.'''
    
    def __init__(self, yearmonth_str, temporal_resolution_code, region, run_details, parameter_details, network_details):

        #add passed variables to self
        self.yearmonth_str = yearmonth_str
        self.temporal_resolution_code = temporal_resolution_code
        self.region = region
        self.run_details = run_details
        self.parameter_details = parameter_details
        self.network_details = network_details

        self.run_details['log_file_str'] += 'CONCATENATING {} STATION NETCDFs\n'.format(self.yearmonth_str)


    def do_work(self):
        '''Function which does executes the functions of the class in a pipeline'''

        #create monthly netCDF
        self.create_monthly_netCDF()


    def create_monthly_netCDF(self):

        #set network directory where to read/write data
        if self.region == 'GLOBAL':
            network_write_dir = self.run_details['network']
        else:
            network_write_dir = '{}_{}'.format(self.run_details['network'], self.region)

        #get output temporal resolution specific variables
        temporal_resolution_vars = standard_temporal_resolutions[self.temporal_resolution_code]

        #get specific year and month
        year = self.yearmonth_str[:4]
        month = self.yearmonth_str[-2:]

        #get all relevant station netCDF files in yearmonth
        station_files = sorted(glob.glob(self.run_details['data_root'] + '{}/{}/{}/{}/temporary/{}/{}/*.nc'.format(network_write_dir,self.run_details['ghost_version'],temporal_resolution_vars['temporal_resolution_path'],self.parameter_details['bsc_parameter_name'], year, month)))

        #create new netCDF file for yearmonth
        netCDF_fname = self.run_details['data_root'] + '{}/{}/{}/{}/{}_{}.nc'.format(network_write_dir,self.run_details['ghost_version'],temporal_resolution_vars['temporal_resolution_path'],self.parameter_details['bsc_parameter_name'],self.parameter_details['bsc_parameter_name'],self.yearmonth_str)

        # concatenate station netCDFs (put in while loop to ensure job completes successfully)
        #at same time apply compression (-L 1 = deflation level 1), and do not write operation history (-h)
        concat_not_done = True
        while concat_not_done:
            submit_list = ['ncrcat', '-h', '-L', '1']
            submit_list.extend(station_files)
            submit_list.append(netCDF_fname)
            concat_process =  subprocess.Popen(submit_list, stdout=subprocess.PIPE)
            concat_status = concat_process.communicate()[0]
            concat_return_code = concat_process.returncode
            if concat_return_code != 0:
                #delete temporary non-completed file/s
                files_to_del = glob.glob(self.run_details['data_root'] + '{}/{}/{}/{}/{}_{}*'.format(network_write_dir,self.run_details['ghost_version'],temporal_resolution_vars['temporal_resolution_path'],self.parameter_details['bsc_parameter_name'],self.parameter_details['bsc_parameter_name'],self.yearmonth_str))
                for f in files_to_del:      
                    os.remove(f)
                #time out for 60 seconds and try again
                time.sleep(60)
                continue

            #change record (unlimited) station dimension to be fixed  
            #at same time apply compression (-L 1 = deflation level 1)
            submit_list = ['ncks', '-h', '-O', '-L', '1', '--fix_rec_dmn', 'station', netCDF_fname, netCDF_fname]
            record_process =  subprocess.Popen(submit_list, stdout=subprocess.PIPE)
            record_status = record_process.communicate()[0]
            record_return_code = record_process.returncode
            if record_return_code != 0:
                #delete temporary non-completed file/s
                files_to_del = glob.glob(self.run_details['data_root'] + '{}/{}/{}/{}/{}_{}*'.format(network_write_dir,self.run_details['ghost_version'],temporal_resolution_vars['temporal_resolution_path'],self.parameter_details['bsc_parameter_name'],self.parameter_details['bsc_parameter_name'],self.yearmonth_str))
                for f in files_to_del:      
                    os.remove(f)
                #time out for 60 seconds and try again
                time.sleep(60)
                continue
            else:
                concat_not_done = False
        
        #give 770 permissions for file and make owner bsc32
        set_file_permissions_ownership(netCDF_fname)

        #return valid process logfile (0)
        self.run_details['log_file_str'] += str((time.time() - self.run_details['stage_process_start_time'])/60.)
        create_GHOST_stage_logfile(0,self.run_details,previous_stage_data_files=station_files)