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
        
    
    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)
        dset.resize(dset.shape[0] + 1, axis=0)   # increment by the amount of new data
        dset[-1 ,0] = data
        

    def _create_logfile(self, prefix='fdi'):
        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)
        logger.debug('Creating logfile %s', fpath)
        try:
            self._fd = h5py.File(fpath, 'w')
        except:
            logger.exception('HDF5 file creation failed.')
            raise
        

    def new_log(self):
        self._create_logfile()
        
        self._create_group('motor data')

        self._create_dataset('motor data', 'time', 'seconds')
        self._create_dataset('motor data', 'voltage', 'Volts', daq='9239')
        self._create_dataset('motor data', 'current', 'Amps', daq='9239')
        self._create_dataset('motor data', 'str pot', 'Volts', daq='9239')
        self._create_dataset('motor data', 'encoder', 'counts', daq='9361')


    def append(self, time, data):
        self._append_data_to_dataset_in_group(time, 'time', 'motor data')
        self._append_data_to_dataset_in_group(data[0], 'voltage', 'motor data')
        self._append_data_to_dataset_in_group(data[1], 'current', 'motor data')
        self._append_data_to_dataset_in_group(data[2], 'str pot', 'motor data')
        self._append_data_to_dataset_in_group(data[3], 'encoder', 'motor data')


    def stop(self):
        if self._fd:
            self._fd.close()
