#!python
'''G5list
  List datasets (or groups of datasets) in a HDF5-file.

Usage:
  G5list [options] [--fold ARG]... <source>

Arguments:
  <source>    HDF5-file.

Options:
  -f, --fold=ARG        Fold paths.
  -d, --max-depth=ARG   Maximum depth to display.
  -r, --root=ARG        Start a certain point in the path-tree. [default: /]
      --info            Print information: shape, dtype.
  -h, --help            Show help.
      --version         Show version.

(c - MIT) T.W.J. de Geus | tom@geus.me | www.geus.me | github.com/tdegeus/GooseHDF5
'''

# ==================================================================================================

# temporary fix: suppress warning from h5py
import warnings
warnings.filterwarnings("ignore")

import numpy as np
import sys, os, re, h5py, docopt, GooseHDF5

# ==================================================================================================

def confirm(message='Proceed [y/n]?\n'):
  r'''
Prompt user for confirmation. The function loops until the user responds with

* 'y' -> True
* 'n' -> False
  '''

  while True:

    # - prompt message, get user's response
    user = input(message)

    # - check response
    if not user                     : print('Please enter y or n.'); continue
    if user not in ['y','Y','n','N']: print('Please enter y or n.'); continue
    if user     in ['y','Y'        ]: return True
    if user     in ['n','N'        ]: return False

# ==================================================================================================

def error(message):
  r'''
Print error message and quit.
  '''

  print(message)

  sys.exit(1)

# ==================================================================================================

def quit(message):
  r'''
Prompt user for confirmation. If the response is negative this function quits the program.
  '''

  if not confirm(message):
    sys.exit(1)

# ==================================================================================================

def isfile(fname):
  r'''
Check if a fail exists, quit otherwise.
  '''

  if not os.path.isfile(fname):
    error('"{0:s}" does not exist'.format(fname))

# ==================================================================================================

# parse command-line options
# --------------------------

args = docopt.docopt(__doc__,version='0.0.2')

# check files
# -----------

# files that are required to exist
isfile(args['<source>'])

# get paths
# ---------

# open file
try:
  source = h5py.File(args['<source>'], 'r')
except:
  print('Error reading "{0:s}"'.format(args['<source>']))
  sys.exit(1)

# get iterator to data-sets
paths = GooseHDF5.getpaths(source, root=args['--root'], max_depth=args['--max-depth'], fold=args['--fold'])

# print
# -----

# print without info
if not args['--info']:
  for path in paths:
    print(path)

# print with info
if args['--info']:

  out = {
    'path'  : [],
    'size'  : [],
    'shape' : [],
    'dtype' : [],
  }

  for path in paths:
    if path in source:
      data = source[path]
      out['path' ] += [path]
      out['size' ] += [str(data.size)]
      out['shape'] += [str(data.shape)]
      out['dtype'] += [str(data.dtype)]
    else:
      out['path' ] += [path]
      out['size' ] += ['-']
      out['shape'] += ['-']
      out['dtype'] += ['-']

  width = {}
  for key in out:
    width[key] = max([len(i) for i in out[key]])
    width[key] = max(width[key], len(key))

  fmt = '{0:%ds} {1:%ds} {2:%ds} {3:%ds}' % (width['path'], width['size'], width['shape'], width['dtype'])

  print(fmt.format('path', 'size', 'shape', 'dtype'))
  print(fmt.format('='*width['path'], '='*width['size'], '='*width['shape'], '='*width['dtype']))

  for i in range(len(out['path'])):
    print(fmt.format(out['path'][i], out['size'][i], out['shape'][i], out['dtype'][i]))

# close file
# ----------

source.close()
