#!python
# -*- coding: latin-1 -*-

#
# joinfiles
#
# Concaténation de fichiers binaires (ou textes)
#   en un seul fichier
#

# (c) Olivier Pirson --- olivier_pirson_opi@yahoo.fr
# DragonSoft DS --- http://www.opimedia.be/DS/
# Débuté le 18 novembre 2011
# v.01.00.00 --- 18 novembre 2011
#####################################################
VERSION = '01.00.00 --- 2011 November 18'

import collections
import sys

if __debug__:
    assert sys.version_info[0] >= 3, ('Require Python 3 or better', sys.version)



#############
# Fonctions #
#############
def help_msg():
    """Affiche le message d'aide sur la sortie des erreurs
    et termine le programme par un code d'erreur 1"""
    print("""joinfiles [-o filename] filename [filename [...]]

  (c) Olivier Pirson --- olivier_pirson_opi@yahoo.fr
       DragonSoft DS --- http://www.opimedia.be/DS/
          v.{0}

  Concatenate filename [filename [...]] into on file

  Options:
    -o filename   destination filename ('joinfiles.all' by default).

    --help        Print this message on error output and exit by error code 1.""".format(VERSION), file=sys.stderr)

    exit(1)


def joinfiles(src_filenames, dest_filename, out=None):
    """Concatène la suite de fichiers dont les noms sont dans src_filenames
    en un seul fichier de nom dest_filename

    Si out != None
    alors des informations sur la progression des opérations sont envoyées sur le flux de sortie out

    Si tout c'est bien passé alors renvoie True
                             sinon renvoie False

    Pre: src_filenames: Sequence de string
         dest_filename: string
         out: None ou flux de sortie

    Result: bool"""
    assert isinstance(src_filenames, collections.Sequence), type(src_filenames)
    assert isinstance(dest_filename, str), type(dest_filename)

    if out != None:
        print('Destination file: "{}"'.format(dest_filename), end='', file=out)
    try:
        dest = open(dest_filename, mode='wb')
    except:
        if out != None:
            print(': !!! creation failed', file=out)

        return False

    if out != None:
        print('', file=out)

    error = False
    nb = 0
    for filename in src_filenames:
        nb += 1
        if out != None:
            print('{}: "{}"'.format(nb, filename), end=': ', file=out)
        try:
            src = open(filename, mode='rb')
        except:
            if out != None:
                print('!!! open failed', file=out)

            error = True
            continue

        i = 0
        while True:
            data = src.read(1024*1024)
            if not data:
                break
            dest.write(data)
            if out != None:
                print(i, end='', file=out)
            sys.stdout.flush()
            i = (i + 1 if i < 10
                 else 0)

        src.close()
        if out != None:
            print('', file=out)

    dest.close()

    return error



########
# Main #
########
if __name__ == '__main__':
    src_filenames = []  # liste des noms de fichier source
    dest_filename = 'joinfiles.all'  # nom du fichier destination


    # Récupère les arguments de la ligne de commande
    i = 1
    while  i < len(sys.argv):
        arg = sys.argv[i]

        if arg[0] == '-':
            if (arg == '-o') and (i + 1 < len(sys.argv)):
                i += 1
                dest_filename = sys.argv[i]
            else:
                help_msg()
        else:
            src_filenames.append(arg)

        i += 1


    # Effectue la concaténation
    if joinfiles(src_filenames, dest_filename, sys.stderr):
        print('!!! error', file=sys.stderr)
