#!/usr/bin/env python

'''
A program to update existing *.lic file checksum values in a given
directory tree.

Mask of files to process may be specified (defaults to '*.lic').

Always recurses down into sub-directories.
'''


import sys
import os
import getopt
import fnmatch
import xml.etree.cElementTree as etree

try:
    from anuga.utilities.system_tools import compute_checksum
except ImportError:
    print("Can't import 'anuga.utilities.system_tools'?")
    print('Please ensure PYTHONPATH environment variable is correct.')
    print("It's currently: %s" % os.getenv('PYTHONPATH'))
    sys.exit(10)


# default XML encoding
DefaultEncoding = 'iso-8859-1'

# verbose flag
Verbose = False


def process_file(dirname, fname):
    '''Update checksum in a licence file.'''

    # read in the licence file (XML)
    lic_tree = etree.ElementTree()
    input_filename = os.path.join(dirname, fname)
    lic_tree.parse(input_filename)

    if Verbose:
        print('Updating %s' % input_filename)

    # process every <datafile> tagset - update checksum
    datafiles = lic_tree.getiterator('datafile')
    for f in datafiles:
        # get 'filename' element text
        filename = f.find('filename')
        if filename is None:
            msg = ('Badly formed licence XML in file %s:\n%s'
                   % (input_filename, etree.dump(f)))
            raise RuntimeError, msg

        # get 'checksum' element text
        checksum = f.find('checksum')
        if checksum is None:
            msg = ('Badly formed licence XML in file %s:\n%s'
                   % (input_filename, etree.dump(f)))
            raise RuntimeError, msg

        # update the 'checksum' element from the file
        controlled_filename = os.path.join(dirname, filename.text)
        if (not os.path.exists(controlled_filename) or
            not os.path.isfile(controlled_filename)):
            print('?' * 80)
            print("Licence file %s\nrefers to %s\nwhich doesn't exist!?"
                  % (input_filename, controlled_filename))
            print('?' * 80 + '\n')
            continue
        new_checksum = compute_checksum(controlled_filename)
        checksum.text = str(new_checksum)

    # write updated XML data back to file
    new_fname = os.path.join(dirname, fname+'._NEW_')
    lic_tree.write(new_fname, DefaultEncoding)
    os.rename(new_fname, input_filename)


def process_one_dir(mask, dirname, names):
    '''Update all licence files in directory that match 'mask'.'''

    for fname in names:
        if fnmatch.fnmatch(fname, mask):
            process_file(dirname, fname)


def usage(msg=None):
    '''Print helpful usage one-liner.'''

    if msg:
        print(msg)

    print('usage: update_lic_checksum [-m <lic_mask>] <directory>')


def main(argv):
    '''Main function - parse args and start the process.'''

    global Verbose

    # parse command line args
    try:
        opts, args = getopt.gnu_getopt(argv, 'hm:v',
                                       ['help', 'mask=', 'verbose'])
    except:
        usage()
        return 10

    file_mask = '*.lic'
    for (opt, opt_arg) in opts:
        if opt in ['-m', '--mask']:
            file_mask = opt_arg
        elif opt in ['-h', '--help']:
            usage()
            return 10
        elif opt in ['-v', '--verbose']:
            Verbose = True
        else:
            usage()
            return 10

    if len(args) != 1:
        usage()
        return 10
    dir_path = args[0]

    # walk all directories under path, look for licence files
    os.path.walk(dir_path, process_one_dir, file_mask)


sys.exit(main(sys.argv[1:]))
