#!/opt/ddr-local/venv/ddrlocal/bin/python
#
# This file is part of ddr-cmdln/ddr
#
#

description = """Updates a single field in multiple JSON files with a specified value."""

epilog = """* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
WARNING! THIS SCRIPT IS AN EXTREMELY STUPID BLUNT INSTRUMENT!
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

It sets all the status fields in all the collection.json and entity.json files
of a collection to "completed".  You can specify the collection directory but
not much else.

It writes a logfile to the current directory.
It does not commit the changes!

Example:

    # Update collection and entity metadata in a collection
    $ ddr-massupdate collection,entity /var/www/media/base/ddr-testing-123

    # Update all metadata files in a collection
    $ ddr-massupdate collection,entity,file /var/www/media/base/ddr-testing-123

    # Dry run: show which files would be changed by an operation
    $ ddr-massupdate -d collection,entity,file /var/www/media/base/ddr-testing-123

ddr-public - ddr-massupdate"""

import argparse
from datetime import datetime
import json
import logging
import os
import re
import sys

import envoy

from DDR import format_json
from DDR import fileio
from DDR import models
from DDR import identifier
from DDR import util


FIELD_NAME = 'status'
NEW_VALUE = 'inprocess'


def dtfmt(dt):
    """Consistent date format.
    """
    return dt.strftime('%Y-%m-%dT%H:%M:%S.%f')

def logprint(filename, msg):
    """Print to log file and console, with timestamp.
    """
    msg = '%s - %s\n' % (dtfmt(datetime.now()), msg)
    with open(filename, 'a') as f:
        f.writelines([msg])
    print(msg.strip('\n'))

def logprint_nots(filename, msg):
    """Print to log file and console, no timestamp.
    """
    msg = '%s\n' % msg
    with open(filename, 'a') as f:
        f.writelines([msg])
    print(msg.strip('\n'))

def find_files(basedir, filetypes):
    """Looks for filenames in the list.
    
    Just does stupid matching, not real regex or anything.
    """
    allpaths = util.find_meta_files(basedir, recursive=True, force_read=True)
    paths = []
    for model in filetypes:
        prog = identifier.META_FILENAME_REGEX[model]
        these = [path for path in allpaths if re.search(prog, path)]
        paths.extend(these)
    return paths

def update_file(json_path, field_name, new_value):
    """Updates specified field in json file with a value and saves.
    """
    with open(json_path, 'r') as f:
        data = json.loads(f.read())
    
    for field in data:
        fname = field.keys()[0]
        if fname == field_name:
            field[fname] = new_value
    
    fileio.write_text(format_json(data), json_path)



def main():

    parser = argparse.ArgumentParser(description=description, epilog=epilog,
                                     formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('models', help="Comma-separated list of models to change.")
    parser.add_argument('collection', help='Absolute path to source collection repository.')
    parser.add_argument('-d', '--dryrun', action='store_true', help="Don't change anything, just list files that would be changed.")
    
    args = parser.parse_args()
    collection_path = os.path.realpath(args.collection)
    collection_id = os.path.basename(collection_path)
    LOG = os.path.join(os.getcwd(), 'ddr-massupdate-%s.log' % collection_id)
    
    selected_file_types = args.models.split(',')
    for model in selected_file_types:
        logprint(LOG, 'Matching %ss' % model)
    if not len(selected_file_types):
        print('Error: Select at least one type of file to match.')
        sys.exit(1)
    
    started = datetime.now()
    if args.dryrun:
        logprint(LOG, 'DRY RUN (no files will be changed)')
    logprint(LOG, 'Processing %s' % collection_path)
    paths = find_files(collection_path, selected_file_types)
    if args.dryrun:
        logprint(LOG, '%s files.' % len(paths))
        for path in paths:
            logprint(LOG, path)
    else:
        logprint(LOG, '%s files.' % len(paths))
        for path in paths:
            update_file(path, FIELD_NAME, NEW_VALUE)
    
    finished = datetime.now()
    elapsed = finished - started
    logprint(LOG, 'DONE!')
    logprint_nots(LOG, '%s elapsed' % elapsed)
    print('Wrote log to %s' % LOG)
    print('')

if __name__ == '__main__':
    main()
