""" Class to solve the creation, serialisation etc. of NetCDF files used
    in the BioVel Biome-BGC project. The module is used from the
    :mod:`ResultEvaluator`.

"""

# Copyright (c) 2014 MTA Centre for Ecological Research
# Distributed under the GNU GPL v3. For full terms see the file LICENSE.

from Scientific.IO import NetCDF

class BBGCNetCDF:
    """ Container of the result data of a MonteCarlo Biome-BGC
        experiment

    """

#-----------------------------------------------------------------------
    def __init__(self, file_name, repeat_num):
        """
        BBGC NetCDF output.

        :param file_name: Name of the netcdf file.
        :type file_name: str.

        """

        #self.project_dir = project_dir
        #self.project_name = project_name
        self.netcdf = NetCDF.NetCDFFile(file_name, 'w')
        #print('RepeatNum: '+str(repeat_num))
        self.netcdf.createDimension('repeatNum', repeat_num)

#-----------------------------------------------------------------------
    def insert_rand_input_params(self, param_names, param_values):
        """
            Insert the values into a matrix and the names of randomised
            input variables into a 2D character array, where width
            of the array is the length of the longest name.

            :param param_names: List of the randomised input parameter names.
            :type param_names: List of strings.
            :param param_values: Matrix of the input parameters * repeat num.
            :type param_values: List of float lists.

        """
        # parameter_names matrix
        max_name_len = max(map(len, param_names))
        name_list = []
        for name in param_names:
            name_list.append(list(name.encode('ascii', 'ignore')) + ([' '] * (max_name_len - len(name)) ))
        #print(name_list)
        self.netcdf.createDimension('inputParamNum', len(param_names))
        self.netcdf.createDimension('inputParamMaxLen', max_name_len)
        self.netcdf.createVariable('inputParamNames','c',('inputParamNum','inputParamMaxLen'))
        tmp_var = self.netcdf.variables['inputParamNames']
        for i in range(0,len(param_names)):
            for j in range(0,max_name_len):
                #print(name_list[i][j])
                tmp_var[i,j] = name_list[i][j]

        #tmp_var.assignValue(name_list)

        # randomised input parameter matrix
        self.netcdf.createVariable('inputParams', 'f', ('repeatNum','inputParamNum'))
        tmp_var = self.netcdf.variables['inputParams']
        tmp_var.assignValue(param_values)

#-----------------------------------------------------------------------
    def insert_outputs(self, annual_variables, daily_variables,
         annout=None, monavgout=None, annavgout=None, dayout=None):
        """ Insert the output variables into the NetCDF file

            :param annual_variables: Ids of annual output variables.
            :type daily_variables: List of ints.
            :param daily_variables: Ids of daily output variables.
            :type daily_variables: List of ints.
            :param annout: Values of annual output. Repeat num x var num. x years.
            :type annout: 3D float List.
        """
        year_num_dim = False

        ann_var_dim_name = 'annualVarNum'
        ann_var_ids_name = 'annualVarIds'
        self.netcdf.createDimension('annualVarNum',len(annual_variables))
        self.netcdf.createVariable('annualVarIds', 'i', ('annualVarNum',))
        self.netcdf.variables['annualVarIds'].assignValue(annual_variables)

        day_var_dim_name = 'dailyVarNum'
        day_var_ids_name = 'dailyVarIds'
        self.netcdf.createDimension(day_var_dim_name,len(daily_variables))
        self.netcdf.createVariable(day_var_ids_name, 'i', (day_var_dim_name,))
        self.netcdf.variables[day_var_ids_name].assignValue(daily_variables)

        if annout:
            self.netcdf.createDimension('yearNum',len(annout[0]))
            year_num_dim = True
            self.netcdf.createVariable('annout', 'f', ('repeatNum' ,'yearNum' ,ann_var_dim_name))
            self.netcdf.variables['annout'].assignValue(annout)
        if monavgout:
            self.netcdf.createDimension('monthNum',len(monavgout[0]))
            self.netcdf.createVariable('monavgout', 'f', ('repeatNum','monthNum' ,day_var_dim_name))
            self.netcdf.variables['monavgout'].assignValue(monavgout)
        if annavgout:
            if not year_num_dim:
                self.netcdf.createDimension('yearNum',len(annavgout[0]))
            self.netcdf.createVariable('annavgout', 'f', ('repeatNum','yearNum' ,day_var_dim_name))
            self.netcdf.variables['annavgout'].assignValue(annavgout)
        if dayout:
            self.netcdf.createDimension('dayNum',len(dayout[0]))
            self.netcdf.createVariable('dayout', 'f', ('repeatNum','dayNum' ,day_var_dim_name))
            self.netcdf.variables['dayout'].assignValue(dayout)



#-----------------------------------------------------------------------
    def close(self):
        self.netcdf.close()
