#!/usr/bin/env python
'''
    Metadata anonymisation toolkit - CLI edition
'''

import sys
import xml.sax
import optparse

import hachoir_core

from MAT import mat
from MAT import strippers


def parse():
    '''
        Get, and parse options passed to the program
    '''
    parser = optparse.OptionParser(usage='%prog [options] files\n\
The default behaviour is to clean files given in argument')
    options = optparse.OptionGroup(parser, 'Options')
    options.add_option('--add2archive', '-a', action='store_true',
        default=False, help='Add to output archive non-supported filetypes')
    options.add_option('--backup', '-b', action='store_true', default=False,
        help='Keep a backup copy')
    options.add_option('--force', '-f', action='store_true', default=False,
        help='Don\'t check if files are clean before cleaning')
    options.add_option('--low-pdf-quality', '-L', action='store_true', default=False,
        help='Produces a lighter, but lower quality PDF')

    info = optparse.OptionGroup(parser, 'Informations')
    info.add_option('--check', '-c',  action='store_true', default=False,
        help='Check if a file is free of harmful metadatas')
    info.add_option('--display', '-d', action='store_true', default=False,
        help='List all the harmful metadata of a file without removing them')
    info.add_option('--list', '-l', action='store_true', default=False,
        help='List all supported fileformat')
    info.add_option('--version', '-v', action='callback',
        callback=display_version, help='Display version and exit')
    parser.add_option_group(options)
    parser.add_option_group(info)

    values, arguments = parser.parse_args()
    if not arguments and not values.list:
        # if no argument and no files are passed,
        # print help and exit
        parser.print_help()
    return values, arguments


def display_version(*_):
    '''
        Display the program's version, and exit
    '''
    print('Metadata Anonymisation Toolkit version %s') % mat.__version__
    print('Hachoir version %s') % hachoir_core.__version__
    sys.exit(0)


def list_meta(class_file, filename, force):
    '''
        Print all the metadata of 'filename' on stdout
    '''
    print('[+] File %s :' % filename)
    if not force and class_file.is_clean():
        print('No harmful metadata found')
    else:
        meta = class_file.get_meta()
        print ('Harmful metadata found:')
        if meta:
            for key, value in class_file.get_meta().iteritems():
                print('\t' + key + ' : ' + str(value))


def is_clean(class_file, filename, force):
    '''
        Say if 'filename' is clean or not
    '''
    if class_file.is_clean():
        print('[+] %s is clean' % filename)
    else:
        print('[+] %s is not clean' % filename)


def clean_meta(class_file, filename, force):
    '''
        Clean the file 'filename'
    '''
    print('[+] Cleaning %s' % filename)
    if not force and class_file.is_clean():
        print('%s is already clean' % filename)
    else:
        if class_file.remove_all():
            print('%s cleaned !' % filename)
        else:
            print('Unable to clean %s', filename)


def list_supported():
    '''
        Print all supported fileformat, and exit
    '''
    handler = mat.XMLParser()
    parser = xml.sax.make_parser()
    parser.setContentHandler(handler)
    path = mat.get_formats()
    with open(path, 'r') as xmlfile:
        parser.parse(xmlfile)

    for item in handler.list:
        if strippers.STRIPPERS.has_key(item['mimetype'].split(',')[0]):
            print('%s (%s)' % (item['name'], item['extension']))
            print('\tsupport : ' + item['support'])
            print('\tmetadata : ' + item['metadata'])
            print('\tmethod : ' + item['method'] + '\n')
            if item['support'] == 'partial':
                print('\tremaining : ' + item['remaining'] + '\n')
    sys.exit(0)


def main():
    '''
        main function : get args, and launch the appropriate function
    '''
    args, filenames = parse()

    #func receive the function correponding to the options given as parameters
    if args.display:  # only print metadatas
        func = list_meta
    elif args.check:  # only check if the file is clean
        func = is_clean
    elif args.list:  # print the list of all supported format
        list_supported()
    else:  # clean the file
        func = clean_meta

    for filename in filenames:
        class_file = mat.create_class_file(filename, args.backup,
            add2archive=args.add2archive, low_pdf_quality=args.low_pdf_quality)
        if class_file:
            func(class_file, filename, args.force)
        else:
            print('Unable to process %s' % filename)

if __name__ == '__main__':
    main()
