#!/usr/bin/env python

'''
Copyright (c) Contributors to the Apptainer project, established as
  Apptainer a Series of LF Projects LLC.
  For website terms of use, trademark policy, privacy policy and other
  project policies see https://lfprojects.org/policies

Copyright (c) 2017-2018, Sylabs, Inc. All rights reserved.

Copyright (c) 2015-2017, Gregory M. Kurtzer. All rights reserved.
Copyright (c) 2017, Vanessa Sochat All rights reserved.

Copyright (c) 2016, The Regents of the University of California, through
Lawrence Berkeley National Laboratory (subject to receipt of any required
approvals from the U.S. Dept. of Energy).  All rights reserved.

This software is licensed under a customized 3-clause BSD license.  Please
consult LICENSE file distributed with the sources of this project regarding
your rights to use or distribute this software.

NOTICE.
This Software was developed under funding from the U.S. Department of
Energy and the U.S. Government consequently retains certain rights. As such,
the U.S. Government has been granted for itself and others acting on its
behalf a paid-up, nonexclusive, irrevocable, worldwide license in the Software
to reproduce, distribute copies to the public, prepare derivative works, and
perform publicly and display publicly, and to permit other to do so.
'''

import os
import re
import sys
sys.path.append('../libexec/python')  # noqa

from sutils import (
    get_fullpath,
    read_file,
    write_file
)

from message import bot
import optparse


def get_parser():

    description = "apptainer configuration parsing helper in python"
    parser = optparse.OptionParser(description=description)

    # Configuration defaults header
    help = "configuration defaults header file (../src/lib/config_defaults.h)"
    parser.add_option("--defaults",
                      dest='defaults',
                      help=help,
                      type=str)

    # input configuration file
    help = "the configuration input file path (apptainer.conf.in)"
    parser.add_option("--infile",
                      dest='infile',
                      help=help,
                      type=str)

    # Output configuration file
    help = "the configuration output file path (apptainer.conf)"
    parser.add_option("--outfile",
                      dest='outfile',
                      help=help,
                      type=str)

    return parser


def main():
    '''parse configuration options and produce
       configuration output file
    '''
    bot.info("\n*** STARTING PYTHON CONFIGURATION HELPER ****")
    parser = get_parser()

    try:
        (args, options) = parser.parse_args()
    except Exception:
        bot.error("Input args to %s improperly set, exiting."
                  % os.path.abspath(__file__))
        parser.print_help()
        sys.exit(1)

    # Check for required args
    [check_required(parser, arg) for arg in [args.defaults,
                                             args.infile,
                                             args.outfile]]

    # Run the configuration
    configure(args)


def check_required(parser, arg):
    '''check_required arg checks that an argument is defined.
    It is a workaround for missing required parameter of argparse
    :param parser: the parser
    :param arg: the argument
    '''
    if not arg:   # if filename is not given
        parser.error('Missing required argument.')
        parser.print_help()
        sys.exit(1)


def configure(args):

    # Get fullpath to each file, and concurrently check that exists
    defaultfile = get_fullpath(args.defaults)  # ../src/lib/config_defaults.h
    infile = get_fullpath(args.infile)         # apptainer.conf.in

    # Find define statements
    define_re = re.compile("#define ([A-Z_]+) (.*)")

    # Read in input and default files
    defaultfile = read_file(defaultfile)
    data = "".join(read_file(infile))

    # Lookup for values we want replaced
    lookup = {'0': 'no',
              '1': 'yes'}

    defaults = {}
    # Read in defaults to dictionary
    for line in defaultfile:
        match = define_re.match(line)
        if match:
            key, value = match.groups()

            # Maintain the original default set by user
            defaults[key] = value

            # Use parsed value for final config
            new_value = value.replace('"', '')
            if new_value in lookup:
                new_value = lookup[new_value]
            data = data.replace("@" + key + "@", new_value)

    # Write to output file
    outfile = "%s.tmp" % args.outfile
    write_file(outfile, data)
    os.rename(outfile, args.outfile)

    bot.info("*** FINISHED PYTHON CONFIGURATION HELPER ****\n")


if __name__ == '__main__':
    main()
