#!/opt/ddr-local/venv/ddrlocal/bin/python

#
# ddr-import
#

description = """Imports new entities or files with data from CSV files."""

epilog = """
Verify CSV file, do various integrity checks.

    $ ddr-import check /tmp/ddr-test-123-entity.csv /PATH/TO/ddr/ddr-test-123/

Import entity records.

    $ ddr-import entity /tmp/ddr-test-123-entity.csv /PATH/TO/ddr/ddr-test-123/

Import file records.  Note that slightly different fields are required for
"external" files than for normal ones for which binaries will be imported.

    $ ddr-import file /tmp/ddr-test-123-file.csv /PATH/TO/ddr/ddr-test-123/

Register entity IDs with the ID service API:

    $ ddr-import register /tmp/ddr-test-123-entity.csv /PATH/TO/ddr/ddr-test-123

Most commands require authentication with the ID service. You can specify
username and/or password at the commandline to skip the prompts:

    $ ddr-import check -U gjost -P REDACTED ...

You can send all add-file log entries to the same file:

    $ ddr-import file -L /tmp/mylogfile.log ...

Please see "ddr-export --help" for information on exporting CSV files.
---"""


import argparse
from datetime import datetime
import getpass
import logging
import os
import sys
import traceback

from DDR import config
from DDR import batch
from DDR import dvcs
from DDR import identifier
from DDR import idservice

VOCABS_PATH = os.path.join(config.REPO_MODELS_PATH, 'vocab')
AGENT = 'ddr-import'

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(levelname)-8s %(message)s',
    stream=sys.stdout,
)


def log_error(err, debug=False):
    """Print Exception message to log, or traceback to console
    
    @param err: Exception
    @param debug: boolean If True, print traceback to console
    """
    if debug:
        print('************************************************************************')
        traceback.print_exc()
        print('************************************************************************')
    else:
        logging.error('************************************************************************')
        logging.error(err)
        logging.error('************************************************************************')

def idservice_api_login(args):
    """Login to ID service, return auth token and user info; prompt if necessary
    
    @param args: argparse.Namespace Output of argparse.ArgumentParser.parse_args()
    @returns: idservice.IDServiceClient
    """
    if args.username:
        logging.debug('Username: %s' % args.username)
        username = args.username
    else:
        username = raw_input('Username: ')
    if args.password:
        password = args.password
        dummy = ''.join(['*' for n in args.password])
        logging.debug('Password: %s' % dummy)
    else:
        password = getpass.getpass(prompt='Password: ')
    
    ic = idservice.IDServiceClient()
    status1,reason1 = ic.login(username, password)
    if status1 != 200:
        logging.error('Login failed[1]: %s %s' % (status1,reason1))
        sys.exit(1)
    return ic


def main():

    parser = argparse.ArgumentParser(description=description, epilog=epilog,
                                     formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('command', help="Command: 'check', 'entity', 'file', 'register'.")
    parser.add_argument('csv', help='Absolute path to CSV file.')
    parser.add_argument('collection', help='Absolute path to Collection.')
    parser.add_argument('-i', '--idservice', help='URL of ID service, if different from configs.')
    parser.add_argument('-N', '--nocheck', action='store_true', help='Do not run checking/validation (large collections may take time).')
    parser.add_argument('-d', '--dryrun', action='store_true', help="Simulated run-through; don't modify files.")
    parser.add_argument('-F', '--fromto', help="Only import specified rows. Use Python list syntax e.g. '523:711' or ':200' or '100:'.")
    parser.add_argument('-R', '--remove', action='store_true', help="Remove untracked files (use with 'cleanup').")
    parser.add_argument('-D', '--debug', action='store_true', help='Print error tracebacks.')
    parser.add_argument('-u', '--user', help='Git user name (required if importing)')
    parser.add_argument('-m', '--mail', help='Git user e-mail address (required if importing)')
    parser.add_argument('-U', '--username', help='ID service username')
    parser.add_argument('-P', '--password', help='ID service password')
    parser.add_argument('-l', '--log', help='(optional) Log addfile to this path')
    args = parser.parse_args()
    
    # ensure we have absolute paths (CWD+relpath)
    csv_path = os.path.abspath(os.path.normpath(args.csv))
    collection_path = os.path.abspath(os.path.normpath(args.collection))
    vocabs_path = os.path.normpath(VOCABS_PATH)
    
    # Check args
    if not os.path.exists(csv_path):
        print('ddr-import: CSV file does not exist.')
        sys.exit(1)
    if not (os.path.isfile(csv_path) and os.path.isdir(collection_path)):
        print('ddr-import: CSV filename comes before collection.')
        sys.exit(1)
    if not os.path.exists(collection_path):
        print('ddr-import: Collection does not exist.')
        sys.exit(1)
    
    start = datetime.now()

    ci = identifier.Identifier(collection_path)
    logging.debug(ci)
    logging.debug(ci.path_abs())
    
    idservice_client = None
    
    if (args.command == 'check'):
        idservice_client = idservice_api_login(args)
        chkcsv = batch.Checker.check_csv(csv_path, ci, vocabs_path)
        chkrepo = batch.Checker.check_repository(ci)
        chkeids = batch.Checker.check_eids(chkcsv['rowds'], ci, idservice_client)
        
        tests = 0
        passed = 0
        def passfail(results, tests, passed):
            tests += 1
            if results['passed']:
                passed += 1
            return tests,passed
        tests,passed = passfail(chkcsv, tests, passed)
        tests,passed = passfail(chkrepo, tests, passed)
        tests,passed = passfail(chkeids, tests, passed)
        if passed != tests:
            logging.error('TESTS FAILED--QUITTING!')
            sys.exit(1)
    
    if args.command == 'cleanup':
        repo = dvcs.repository('/var/www/base/ddr-testing-333')
        logging.debug('Resetting staged files')
        dvcs.reset(repo)
        logging.debug('Reverting modified files')
        dvcs.revert(repo)
        if args.remove:
            logging.debug('Removing untracked files')
            dvcs.remove_untracked(repo)
        logging.debug('status:')
        status = dvcs.repo_status(repo)
        logging.debug(status)
        sys.exit(0)
    
    if   args.command == 'entity':
        imported = batch.Importer.import_entities(
            csv_path,
            ci,
            vocabs_path,
            args.user, args.mail,
            AGENT,
            args.dryrun
        )
    
    elif args.command == 'file':
        row_start = 0
        row_end = 9999999
        if args.fromto:
            rowstart,rowend = args.fromto.split(':')
            if rowstart:
                row_start = int(rowstart)
            if rowend:
                row_end = int(rowend)
        imported = batch.Importer.import_files(
            csv_path=csv_path,
            cidentifier=ci,
            vocabs_path=vocabs_path,
            git_name=args.user,
            git_mail=args.mail,
            agent=AGENT,
            log_path=args.log,
            dryrun=args.dryrun,
            row_start=row_start,
            row_end=row_end,
        )
    
    elif args.command == 'register':
        idservice_client = idservice_api_login(args)
        batch.Importer.register_entity_ids(
            csv_path, ci, idservice_client, args.dryrun
        )
        logging.info('IF YOU SEE THIS IT WORKED')
    
    finish = datetime.now()
    elapsed = finish - start
    logging.info('DONE - %s elapsed' % elapsed)


if __name__ == '__main__':
    main()
