#!python
#
#SPDX-License-Identifier: GPL-3.0-only
#
# Copyright (C) 2019 Alberto Pianon <pianon@array.eu>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, version 3.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <https://www.gnu.org/licenses/>.


import sys, argparse, os

from subprocess import Popen, PIPE

from include_pandoc.createaddargs import whereami, create_addargs
from include_pandoc.process_includes import process_file

# suppress (very long) usage info output, but only on help (-h), not on error
# https://stackoverflow.com/a/14591302
import sys as _sys
class MyParser(argparse.ArgumentParser):
    def error(self, message):
        usage = self.usage
        self.usage = None
        self.print_usage(_sys.stderr)
        self.exit(2, '%s: ERROR: %s\n' % (self.prog, message))
        self.usage = usage

# --update option has precedence over any other options
# (that, if present, will be ignored)
if "--update" in sys.argv:
    # check if we can write to the folder where include-pandoc is installed
    if not os.access(whereami(), os.W_OK):
        sys.stderr.write(
            'Cannot write to %s:\n'
            'maybe you need to run "%s --update" with sudo / as root.\n\n' %
            (whereami(), os.path.basename(sys.argv[0]))
        )
        sys.exit(1)
    sys.stdout.write("updating pandoc wrapper... ")
    # calling the function that parses the output of 'pandoc -h'
    # and creates the addargs.py module
    create_addargs()
    sys.stdout.write("DONE!\n\n")
    sys.exit(0)

try:
    from include_pandoc.addargs import addargs_pandoc_version, add_args
except ImportError:
    # this means that the real addargs.py module has not ben created yet,
    # and that only the dummy module copied during installation is present
    sys.stderr.write(
        'ERROR: Wrapper not initialized!\n'
        'Please run "%s --update"\n'
        '(with sudo / as root if you did not install %s as user)\n\n' %
        (sys.argv[0], sys.argv[0])
    )
    sys.exit(1)

p = Popen(['pandoc', '-v'], stdout=PIPE)
v = p.communicate()[0]
# we keep only the first two lines of the output of 'pandoc -v',
# because the content of subsequent lines is user-dependent
# (the current user's pandoc dir is displayed)
version = " ".join(v.splitlines()[:2])
if version != addargs_pandoc_version():
    # this means that probably pandoc has been updated, so the
    # addargs.py module must be regenerated
    sys.stderr.write(
        'ERROR: pandoc version mismatch\n'
        'Please run %s --update\n'
        '(with sudo / as root if you did not install %s as user)\n\n' %
        (sys.argv[0], sys.argv[0])
    )
    sys.exit(1)

parser = MyParser(
   description="Wrapper for pandoc with include processing",
   usage=argparse.SUPPRESS
)

parser.add_argument(
    "input_file", metavar="FILE", nargs='*',
    type=argparse.FileType('r'), default=sys.stdin
)

parser.add_argument(
    '--update', action="store_true", help="update pandoc wrapper"
) # dummy argument, it will never be fired (because such argument
  # is handled directly at the beginning of this script, without
  # using argparse), but we put it here in order that it is displayed
  # in the help page generated by argparse for the -h option

# Now we call the add_args function created by 'include-pandoc --update'
add_args(parser)

# the first argument is this script's filename, skip it
sys.argv.pop(0)

# ns stands for Namespace since parse_args returns a Namespace object
# containing all the options/arguments
ns = parser.parse_args(sys.argv)

pandoc_args = []
for key, value in vars(ns).iteritems():
    if value and key != "input_file":
        # adjust possible inconsistencies in arguments' values
        if type(value) is str:
            value = value.replace("=", ":")
        elif type(value) is list:
            # argparse returns lists even if nargs is set to 1,
            # and returns lists of lists when action is set to "append"
            # (i.e when the same argument may be repeated more than once)
            # f.e --filter=pandoc-coolfilter1 --filter=pandoc-coolfilter2 is
            # 'rendered' as
            # filter=[['pandoc-coolfilter1'], ['pandoc-coolfilter2']]
            # Since pandoc apparently does not support multiple values on the
            # same argument (like --filter filter1 filter2) but only repetitions
            # of the same argument, we simplify things and convert nested lists
            # into simple lists
            value = [
                (
                    v[0].replace("=", ":")
                    if type(v) is list
                    else v.replace("=", ":")
                )
                for v in value
            ]
        # if value is True, it means that it is a 'standalone' argument, that
        # does not require/accept any value (like f.e. '-v'); if value is
        # something else (i.e. a string), it means that it is an argument that
        # requires/accepts values (like f.e. '-t html')
        # Since argparse returns only option long names, we use the
        # corresponding syntax (i.e '--to=html')
        if value == True:
            pandoc_args.append("--%s" % key.replace("_", "-"))
        else:
            if type(value) is str:
                pandoc_args.append('--%s=%s' % (key.replace("_", "-"), value))
            elif type(value) is list:
                for v in value:
                    pandoc_args.append('--%s=%s' % (key.replace("_", "-"), v))



# we need a list of files to process in any case (even if the file is only one)
# to iterate over such list
input_files = ns.input_file if type(ns.input_file) is list else [ns.input_file]

# we call pandoc with args parsed by argparse,
# passing the pre-processed text to stdin
p = Popen(['pandoc'] + pandoc_args, stdout=PIPE, stdin=PIPE)

if not ns.version: # if argument '-v' or '--version' is present,
                   # we do not process any file
    try:
        for f in input_files:
            # this function does the magic: replaces all include statements
            # with the content of the included files
            process_file(f, p.stdin, byte=True)
    except KeyboardInterrupt:
        # when calling 'include-pandoc' with no arguments and no stdin,
        # the console hangs, and one has to interrupt the script with CTRL+C
        # (like it happens with any other command accepting stdin input);
        # this code avoids that python error traceback is printed to console
        # in such a case ( just for esthetic reasons :) )
        sys.stdout.write('\n')
        sys.exit(0)

sys.stdout.write(p.communicate()[0])
p.stdin.close()
sys.exit(0)
