# Copyright (c) 2016-2018 Harald Klimach <harald.klimach@uni-siegen.de>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class FakeSecHead(object):
  """ A class to provide the config file with an prepended section header, if
      none is provided in the file itself.
      Provided for Python 2 at: http://stackoverflow.com/a/2819788/577108
  """
  def __init__(self, fp):
    self.fp = fp
    self.sechead = '[config]\n'

  def readline(self):
    if self.sechead:
      try:
          return self.sechead
      finally:
          self.sechead = None
    else:
      return self.fp.readline()


def get_args():
  """ Get the configuration from the command line and the configuration file.
      This routine returns the configuration arguments in namespace as returned
      by ArgumentParser.parse_args().
  """
  import sys
  import os
  import itertools
  import argparse
  import tools.configargs

  parser = tools.configargs.Configurator(
             default_file = 'series.config',
             formatter_class = argparse.RawDescriptionHelpFormatter,
             description = '''
Generate a time series from multiple restart files.

You might use a configuration file to provide the command line settings
in the form
option: value

For example you may preconfigure the harvester executable name by
harvester: build/atl_harvesting

This script will repeatedly call the harvester executable to create
visualization files and provide a movie file to bind them all together for
easy handling in the visualization tool (usually Paraview, but you might also
use Visit).

The list of files to process can be provided in the configuration as a list
of comma-separated strings to the 'files:' keyword, or as list of arguments to
the script itself.

The input to the harvesting tool is generated by using the provided template,
where the variables file, out and samplelevel, will be replaced by the
corresponding options.
That is, $!out!$ in the template will be replaced by the setting provided by
the --out option, $!file!$ will be replaced by each file found in the list
provided in files and $!samplelevel!$ will be replaced by the value provided
in the --samplelevel argument.
             ''')

  parser.add_argument('--template', '-t',
                      default = 'series.template',
                      help = '''
Specify a harvester template file. Default: series.template.

In the template there are two variables that are replaced: $!out!$ will take
the value provided in the --out option. $!file!$ will be replaced by each of
the files provided in the files argument.
If the template file is not found, a minimal input template is generated
automatically to provide basic visualization of the given files and removed
again after the script successfully finished.
The generated file will have the name provided in this argument.
                      ''')

  parser.add_argument('--run', '-r',
                      default = '',
                      help = '''Run command for the harvester. E.g. for MPI run $ ... -r 'mpirun -np 4'.
  Default is empty.''')

  parser.add_argument('--form', '-f',
                      default = 'pvd',
                      help = 'Which format should be used for the movie file (pvd or visit). Default: pvd')

  parser.add_argument('--harvester', '-x',
                      default = 'harvester',
                      help = 'The path to the harvester binary. Default: harvester')

  parser.add_argument('--lua', '-l',
                      default = 'lua',
                      help = 'The path to the lua binary. Default: lua')

  parser.add_argument('--out', '-o',
                      default = 't_series'+os.sep,
                      help = '''
Output folder. Default: 't_series/'.
This is meant to be used to define the output path in the harvesting
configuration. If this ends in the path separator of the system, it will be
interpreted as a directory and if it does not yet exist, the directory will
be created automatically.
                      ''')

  parser.add_argument('--mesh', '-m', action='store_true',
                      help = 'Visualize mesh only. Default: False.')

  parser.add_argument('--samplelevel', '-s',
                      default = '0',
                      help = '''
Number of levels to subsample. Default: 0.
If there is some higher order data in the input, this option can be used to
define the subresolution to be done for it.
A subsamplelevel of 0 indicates no subsampling to be done, in this case just
the integral mean will be used.
                      ''')

  parser.add_argument('--label', '-n',
                      default = 'visu',
                      help = '''
Label to use in the construction of the output files.
Default: 'visu'. This setting will be passed to the $!label!$ variable
in the template.
                      ''')

  parser.add_argument('--interval', '-i',
                      default = '0',
                      help = '''
Filter out files according to the interval.
Only restarts with a distance of the provided interval setting are
considered for the processing.
This is useful to filter out intermediate restarts, that were written
due to wallclock limits or similar reasons.
The default is 0, which means that all files will be processed.
                             ''')

  parser.add_argument('--begin', '-b',
                      default = '0',
                      help = '''
Point in time to begin the time series, only restarts with a simulation
time greater than this setting will be considered.
If an interval is also provided, they are counted from this beginning
point in time onwards.
Default is 0, which should result in all files being processed.
                             ''')

  parser.add_argument('--end', '-e',
                      default = 'infinity',
                      help = '''
Point in time to end the time series, only restarts with a simulation
time smaller than this setting will be considered.
Default is infinity (process all files).
                             ''')

  loggroup = parser.add_mutually_exclusive_group()
  loggroup.add_argument("-v", "--verbose", action="store_true",
                        help = 'Be more verbose.')
  loggroup.add_argument("-q", "--quiet", action="store_true",
                        help = 'Suppress some output, mainly the output from Harvester.')

  parser.add_argument('files', metavar='file', nargs='*',
                      help = 'Input files to start the conversion on (restart header or mesh prefix).')

  return(parser.parse_args())
