#!python
'''G5find
  Function, loosely based on Linux' find, that searches datasets in a HDF5 file. Based on the
  search result this function will print the filename for a positive match (or print nothing for a
  negative match).

Examples:

  * Perform an action if the file ("data.hdf5") does not contain the field "completed"

      if [ `G5find data.hdf5 --not --iname "completed"` ]; then ... fi

    If the action is to remove the file, the shorthand

      G5find data.hdf5 --not --iname "completed" --remove

    is also available.

Usage:
  G5find [options] <source>...

Arguments:
  <source>    HDF5-file.

Options:
      --iname=ARG       Search for dataset, ignoring the case.
      --find=ARG        Find. [default: (.*)]
      --remove          Remove file for a positive match.
      --not             Execute command only if there are no matches.
      --dry-run         Perform a dry-run.
      --verbose         Print file-path.
  -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')

for fname in args['<source>']:

  # check file
  # ----------

  # files that are required to exist
  isfile(fname)

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

  # print file
  if args['--verbose']: print(fname)

  # initialize list with datasets
  paths = []

  # read datasets
  try:

    # - read file
    source = h5py.File(fname, 'r')
    # - get datasets
    paths = list(GooseHDF5.getdatasets(source))
    # - close file
    source.close()

  except:

    if args['--verbose']: print('Error reading "{0:s}"'.format(fname))

    continue

  # filter datasets
  # ---------------

  # allocate empty list
  match = False

  # loop over all datasets
  for path in paths:

    # - compare name
    if args['--iname']:
      if re.match(args['--iname'], os.path.split(path)[1], re.IGNORECASE):
        match = True
        break

  # remove file
  # -----------

  # remove file only if the path was not found
  if args['--remove'] and ( ( match and not args['--not'] ) or ( not match and args['--not'] ) ):

    if args['--dry-run']: print('rm '+fname); sys.exit(0)
    else                : os.remove(  fname); sys.exit(0)

  # print
  # -----

  if ( match and not args['--not'] ) or ( not match and args['--not'] ):
    print(fname)

