#!/usr/bin/env python3
# encoding: utf-8
'''
zipto7z -- shortdesc

zipto7z is a description

It defines classes_and_methods

@author:     ByCzech

@copyright:  2019 ByCzech. All rights reserved.

@license:    license

@contact:    byczech@gmail.com
@deffield    updated: Updated
'''

import sys
import os

from argparse import ArgumentParser
from argparse import RawDescriptionHelpFormatter

from zipfile import ZipFile
import subprocess
from pathlib import Path

__all__ = []
__version__ = 0.1
__date__ = '2019-09-03'
__updated__ = '2019-09-03'

DEBUG = 0
TESTRUN = 0
PROFILE = 0


class CLIError(Exception):
    '''Generic exception to raise and log different fatal errors.'''

    def __init__(self, msg):
        super(CLIError).__init__(type(self))
        self.msg = "E: %s" % msg

    def __str__(self):
        return self.msg

    def __unicode__(self):
        return self.msg


def main(argv=None):  # IGNORE:C0111
    '''Command line options.'''

    if argv is None:
        argv = sys.argv
    else:
        sys.argv.extend(argv)

    program_name = os.path.basename(sys.argv[0])
    program_version = "v%s" % __version__
    program_build_date = str(__updated__)
    program_version_message = '%%(prog)s %s (%s)' % (program_version, program_build_date)
    program_shortdesc = __import__('__main__').__doc__.split("\n")[1]
    program_license = '''%s

  Created by ByCzech on %s.
  Copyright 2019 ByCzech. All rights reserved.

  Licensed under the Apache License 2.0
  http://www.apache.org/licenses/LICENSE-2.0

  Distributed on an "AS IS" basis without warranties
  or conditions of any kind, either express or implied.

USAGE
''' % (program_shortdesc, str(__date__))

    try:
        # Setup argument parser
        parser = ArgumentParser(description=program_license, formatter_class=RawDescriptionHelpFormatter)
        # parser.add_argument("-r", "--recursive", dest="recurse", action="store_true", help="recurse into subfolders [default: %(default)s]")
        parser.add_argument("-v", "--verbose", dest="verbose", action="count", default=0, help="set verbosity level [default: %(default)s]")
        # parser.add_argument("-i", "--include", dest="include", help="only include paths matching this regex pattern. Note: exclude is given preference over include. [default: %(default)s]", metavar="RE")
        # parser.add_argument("-e", "--exclude", dest="exclude", help="exclude paths matching this regex pattern. [default: %(default)s]", metavar="RE")
        parser.add_argument('-V', '--version', action='version', version=program_version_message)
        parser.add_argument(dest="paths", help="paths to zip file(s) [default: %(default)s]", metavar="path", nargs='+')

        # Process arguments
        args = parser.parse_args()

        paths = args.paths
        verbose = args.verbose
        # recurse = args.recurse
        # inpat = args.include
        # expat = args.exclude

        if verbose > 0:
            print("Verbose mode on")
            # if recurse:
            #    print("Recursive mode on")
            # else:
            #    print("Recursive mode off")

        # if inpat and expat and inpat == expat:
        #    raise CLIError("include and exclude pattern are equal! Nothing will be processed.")

        # Repack ZIP file(s) to 7zip format
        for inpath in paths:
            print("Processing %s to %s:" % (inpath, Path(inpath).stem))
            with ZipFile(inpath, 'r') as myzip:
                for zipmember in myzip.namelist():
                    if verbose > 0:
                        print("  %s" % zipmember, end="")
                    else:
                        print(".", end="", flush=True)

                    proc7z = subprocess.Popen(
                        [
                            '7za', # path to 7za or 7z executable
                            '-mx=9',
                            #'-pPASSWORD',
                            '-si%s' % zipmember,
                            'a',
                            Path(inpath).stem
                        ],
                        stdout=subprocess.PIPE,
                        stdin=subprocess.PIPE
                    )
                    proc7z.stdin.write(myzip.read(zipmember))
                    proc7z.stdin.close()
                    if verbose > 1:
                        print("\n", proc7z.stdout.read().decode('utf-8'))
                        print()
                    proc7z.stdout.close()
                    proc7z.wait()
                    if verbose == 1:
                        print(" ... OK")
                    elif verbose > 1:
                        print("File added successfully")

                if verbose == 0:
                    print()
        return 0

    except KeyboardInterrupt:
        ### handle keyboard interrupt ###
        return 0

    except Exception as e:
        if DEBUG or TESTRUN:
            raise(e)
        indent = len(program_name) * " "
        sys.stderr.write(program_name + ": " + repr(e) + "\n")
        sys.stderr.write(indent + "  for help use --help\n")
        return 2


if __name__ == "__main__":
    if DEBUG:
        # sys.argv.append("-h")
        sys.argv.append("-v")
        # sys.argv.append("-r")
    if TESTRUN:
        import doctest
        doctest.testmod()
    if PROFILE:
        import cProfile
        import pstats
        profile_filename = 'zipto7z_profile.txt'
        cProfile.run('main()', profile_filename)
        statsfile = open("profile_stats.txt", "wb")
        p = pstats.Stats(profile_filename, stream=statsfile)
        stats = p.strip_dirs().sort_stats('cumulative')
        stats.print_stats()
        statsfile.close()
        sys.exit(0)
    sys.exit(main())
