#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
Name: inkscape2png
Porpose: Wrapper interface to perform batch conversion using the
         Inkscape library
Compatibility: Python3
Author: Gianluca Pernigotto <jeanlucperni@gmail.com>
Copyleft - 2024 Gianluca Pernigotto <jeanlucperni@gmail.com>
license: GPL3
Rev: Oct.23.2020 *PEP8 compatible*

DESCRIPTION:
  Given a list of pathnames, recursively converts images found in SVG
  vector format to PNG raster format or to the formats specified in
  the --format argument.

  Assume that the `inkscape` application is installed on the system:

  Note, from version > 1.0 the inkscape syntax may be differ, e.g.:
      use: inkscape -w 1024 -h 1024 input.svg --export-filename output.png
  instead:
      inkscape -z -w 1024 -h 1024 input.svg -e output.png


This file is part of Videomass.

   Videomass 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, either version 3 of the License, or
   (at your option) any later version.

   Videomass 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 Videomass.  If not, see <http://www.gnu.org/licenses/>.
"""


import platform
import subprocess
import os
import glob
import argparse
import sys


def svg2png(delete, paths, parameters, outputdir,
            formatext, recursive: bool = False):
    """
    Iterates on a generator given from `glob.iglob` method.
    glob treats filenames beginning with a dot (.) as special cases,
    so hidden filenames will not be considered. To convert hidden
    filenames use `fnmatch` module instead of `glob` module.

    """
    cmd = ['inkscape', '-z']
    recurs = '**' if recursive else ''

    if formatext == "png":
        outext = ('-e', 'png')
    elif formatext == "svg":
        outext = ('-l', 'svg')
    elif formatext == "ps":
        outext = ('-P', 'ps')
    elif formatext == "eps":
        outext = ('-E', 'eps')
    elif formatext == "pdf":
        outext = ('-A', 'pdf')
    elif formatext == "emf":
        outext = ('-M', 'emf')
    elif formatext == "wmf":
        outext = ('-m', 'wmf')
    else:
        outext = ('-e', 'png')

    for k, v in parameters.items():
        if v:
            cmd.append(k)
            cmd.append(str(v))

    for path in paths:
        for files in glob.iglob(os.path.join(path, recurs, '*.svg'),
                                recursive=recursive
                                ):
            out = outputdir if outputdir else os.path.dirname(files)
            basename = os.path.splitext(os.path.basename(files))
            saveto = os.path.join(f'{out}{basename[0]}.{outext[1]}')
            if platform.system() == 'Windows':
                command = ' '.join(cmd + [files, outext[0], saveto])
            else:
                command = cmd + [files, outext[0], saveto]
            try:
                proc = subprocess.run(command,
                                      capture_output=True,
                                      universal_newlines=True,
                                      check=True,
                                      )
            except FileNotFoundError:
                return "ERROR: 'inkscape': Command not found"

            if proc.returncode:
                return f"ARGS: {proc.args}\nERROR: {proc.stderr}"

            if delete:
                try:
                    os.remove(files)
                except OSError as err:
                    return f"ERROR: {err}"
    return None
    # -------------------------------------------------------------------#


def main():
    """
    Entry-point of the executable (users inputs parser, positional/optional
    arguments)

    """
    descr = ('Wrapper interface to perform batch conversion '
             'using the `Inkscape` library. Given a list of '
             'pathnames, recursively converts images found in '
             'SVG vector format to PNG raster format or to '
             'the formats specified in the --format argument:'
             )
    parser = argparse.ArgumentParser(description=descr)
    parser.add_argument('-W',
                        required=False,
                        metavar='WIDTH',
                        # dest='<int>',
                        type=int,
                        help="width; defaults to the SVG's width",
                        )
    parser.add_argument('-H',
                        required=False,
                        metavar='HEIGHT',
                        type=int,
                        help="height; defaults to the SVG's height",
                        )
    parser.add_argument('-d',
                        required=False,
                        metavar='DPI',
                        type=float,
                        help="pixels per inch; defaults to 90dpi",
                        )
    parser.add_argument('-f', '--format',
                        choices=['png', 'pdf', 'ps', 'eps',
                                 'svg', 'emf', 'wmf'],
                        required=False,
                        type=str,
                        help="save format; defaults to 'png'",
                        )
    parser.add_argument('-p', '--paths',
                        nargs='+',
                        metavar='..DIR ..DIR',
                        required=True,
                        help="Input dirname list separated by spaces",
                        )
    parser.add_argument('-r', '--remove',
                        action='store_true',
                        required=False,
                        help=("If successful, remove all SVG source "
                              "files when finished"),
                        )
    parser.add_argument('-R', '--recursive',
                        action='store_true',
                        required=False,
                        help=("Recursive use (please be careful when "
                              "used with the `-r` argument)"),
                        )
    parser.add_argument('-o', '--output',
                        metavar='..DIR',
                        required=False,
                        help="Provide an output directory to save all files",
                        )
    args = parser.parse_args()

    for pth in args.paths:
        if not os.path.isdir(pth):
            raise NotADirectoryError(f"Invalid or inexistent pathname for "
                                     f"inputdir '{pth}'")
    if args.output:
        if not os.path.isdir(args.output):
            raise NotADirectoryError(f"Invalid or inexistent pathname for "
                                     f"outputdir '{args.output}'")
    if args.format == 'svg' and not args.output:
        raise FileExistsError('Could not overwrite the SVG files themselves. '
                              'You must provide an output pathname using the '
                              '-o argument.')

    param = {'-w': args.W, '-h': args.H, '-d': args.d}

    ret = svg2png(args.remove,
                  args.paths,
                  param,
                  args.output,
                  args.format,
                  args.recursive,
                  )
    if ret:
        sys.exit(ret)
    else:
        print('Done! :-)')
        sys.exit()
    # ----------------------------------------------------------------#


if __name__ == '__main__':
    main()
