import datetime, logging, os

import h5py
import numpy as np

logger = logging.getLogger(__name__)

class HDF5():

    def __init__(self,log_folder):
        self._fd = None
        self._groups = {} # a dict of dicts holding groups and datasets
        self._log_folder = log_folder
        self._fname = None

        
    def __enter__(self):
        return self

    
    def __exit__(self, type, value, traceback):
        self.stop()


    def _create_group(self, group_name):
        ''' Each group is a dict holding two keys: 'group', the object; 'datasets', a dict of datasets where the
        dataset name is the key. '''
        group = self._fd.create_group(group_name)
        self._groups[group_name] = {}
        self._groups[group_name]['group'] = group
        self._groups[group_name]['datasets'] = {}

        
    def _create_dataset(self, group_name, name, units=None, daq=None):
        group = self._get_group(group_name)
        if not group:
            return
        dset = group.create_dataset(name = name, shape = (0, 1), maxshape = (None, 1))
        if units:
            dset.attrs['units'] = units
        if daq:
            dset.attrs['daq'] = daq
        self._groups[group_name]['datasets'][name] = dset
    

    def _get_group(self, group_name):
        if group_name in self._groups:
            return self._groups[group_name]['group']
        else: return None
        

    def _get_dataset_in_group(self, dataset_name, group_name):
        if group_name in self._groups and dataset_name in self._groups[group_name]['datasets']:
            return self._groups[group_name]['datasets'][dataset_name]
        else: return None
        

    def _append_data_to_dataset_in_group(self, data, dataset_name, group_name):
        dset = self._get_dataset_in_group(dataset_name, group_name)
        old_rows = dset.shape[0]
        new_rows = old_rows + data.shape[0]
        dset.resize(new_rows, axis=0)   # increment by the amount of new data
        dset[old_rows:new_rows ,0] = data


    def _append_scalar_to_dataset_in_group(self, data, dataset_name, group_name):
        dset = self._get_dataset_in_group(dataset_name, group_name)
        dset.resize(dset.shape[0] + 1, axis=0)   # increment by the amount of new data
        dset[-1 ,0] = data


    def _create_logfile(self, prefix):
        time_str = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") # append timestamp to the filename     
        fname = prefix + '-' + time_str + '.hdf5'
        fpath = os.path.join(self._log_folder, fname)
        self._fname = fpath
        logger.debug('Creating logfile %s', fpath)
        try:
            self._fd = h5py.File(fpath, 'w')
        except:
            logger.exception('HDF5 file creation failed.')
            raise
        

    def stop(self):
        if self._fd:
            logger.debug('Closing HDF logfile %s.', self._fname)
            self._fd.close()
            self._fd = None

            
    def flush(self):
        if self._fd:
            logger.debug('Flushing HDF logfile %s.', self._fname)
            self._fd.flush()
