#!/usr/bin/env python3

import os
import gnupg
try:
    from . import filehashtools  # @UnusedImport
except SystemError:
    import filehashtools  # @UnresolvedImport @Reimport


def verifier(workingdir, blocksize=16 * 1024 * 1024,
             crc32=False, adler32=False,
             sha1=True, sha224=False, sha256=False,
             sha384=False, sha512=False, md5=True,
             md4=False, ripemd160=False, whirlpool=False):
    """
    For all files in a directory, perform various hash/checksum functions.
    Functions based on boolean arguments, writing the output to a .cksum file.

    :param workingdir: Path containing files you wish to verify.
    :type workingdir: str

    :param blocksize: How much of file to read at once.
    :type blocksize: int

    :param crc32: Use of CRC32. False by default.
    :type crc32: bool

    :param adler32: Use of Adler-32. False by default.
    :type adler32: bool

    :param sha1: Use of SHA-1. True by default.
    :type sha1: bool

    :param sha224: Use of SHA-224. False by default.
    :type sha224: bool

    :param sha256: Use of SHA-256. False by default.
    :type sha256: bool

    :param sha384: Use of SHA-384. False by default.
    :type sha384: bool

    :param sha512: Use of SHA-512. False by default.
    :type sha512: bool

    :param md5: Use of MD5. True by default.
    :type md5: bool

    :param md4: Use of MD4. False by default. Depends on system.
    :type md4: bool

    :param ripemd160: Use of RIPEMD160. False by default. Depends on system.
    :type ripemd160: bool

    :param whirlpool: Use of Whirlpool. False by default. Depends on system.
    :type whirlpool: bool
    """
    hashoutput_crc32 = "CRC32\n"
    hashoutput_adler32 = "ADLER32\n"
    hashoutput_sha1 = "SHA1\n"
    hashoutput_sha224 = "SHA224\n"
    hashoutput_sha256 = "SHA256\n"
    hashoutput_sha384 = "SHA384\n"
    hashoutput_sha512 = "SHA512\n"
    hashoutput_md5 = "MD5\n"
    hashoutput_md4 = "MD4\n"
    hashoutput_ripemd160 = "RIPEMD160\n"
    hashoutput_whirlpool = "WHIRLPOOL\n"
    for file in os.listdir(workingdir):
        if os.path.isdir(os.path.join(workingdir, file)):
            pass  # exclude folders
        elif file.endswith(".cksum"):
            pass  # exclude already generated files
        else:
            print("HASHING:", str(file))
            if adler32:
                print("ADLER32 ", end="")
                result_adler32 = filehashtools.adler32hash(
                    os.path.join(
                        workingdir,
                        file),
                    blocksize)
                hashoutput_adler32 += str(result_adler32.upper())
                hashoutput_adler32 += " "
                hashoutput_adler32 += str(file)
                hashoutput_adler32 += " \n"
            if crc32:
                print("CRC32 ", end="")
                result_crc32 = filehashtools.crc32hash(
                    os.path.join(
                        workingdir,
                        file),
                    blocksize)
                hashoutput_crc32 += str(result_crc32.upper())
                hashoutput_crc32 += " "
                hashoutput_crc32 += str(file)
                hashoutput_crc32 += " \n"
            if md4:
                print("MD4 ", end="")
                result_md4 = filehashtools.md4hash(
                    os.path.join(
                        workingdir,
                        file),
                    blocksize)
                hashoutput_md4 += str(result_md4.upper())
                hashoutput_md4 += " "
                hashoutput_md4 += str(file)
                hashoutput_md4 += " \n"
            if md5:
                print("MD5 ", end="")
                result_md5 = filehashtools.md5hash(
                    os.path.join(
                        workingdir,
                        file),
                    blocksize)
                hashoutput_md5 += str(result_md5.upper())
                hashoutput_md5 += " "
                hashoutput_md5 += str(file)
                hashoutput_md5 += " \n"
            if sha1:
                print("SHA1 ", end="")
                result_sha1 = filehashtools.sha1hash(
                    os.path.join(
                        workingdir,
                        file),
                    blocksize)
                hashoutput_sha1 += str(result_sha1.upper())
                hashoutput_sha1 += " "
                hashoutput_sha1 += str(file)
                hashoutput_sha1 += " \n"
            if sha224:
                print("SHA224 ", end="")
                result_sha224 = filehashtools.sha224hash(
                    os.path.join(
                        workingdir,
                        file),
                    blocksize)
                hashoutput_sha224 += str(result_sha224.upper())
                hashoutput_sha224 += " "
                hashoutput_sha224 += str(file)
                hashoutput_sha224 += " \n"
            if sha256:
                print("SHA256 ", end="")
                result_sha256 = filehashtools.sha256hash(
                    os.path.join(
                        workingdir,
                        file),
                    blocksize)
                hashoutput_sha256 += str(result_sha256.upper())
                hashoutput_sha256 += " "
                hashoutput_sha256 += str(file)
                hashoutput_sha256 += " \n"
            if sha384:
                print("SHA384 ", end="")
                result_sha384 = filehashtools.sha384hash(
                    os.path.join(
                        workingdir,
                        file),
                    blocksize)
                hashoutput_sha384 += str(result_sha384.upper())
                hashoutput_sha384 += " "
                hashoutput_sha384 += str(file)
                hashoutput_sha384 += " \n"
            if sha512:
                print("SHA512 ", end="")
                result_sha512 = filehashtools.sha512hash(
                    os.path.join(
                        workingdir,
                        file),
                    blocksize)
                hashoutput_sha512 += str(result_sha512.upper())
                hashoutput_sha512 += " "
                hashoutput_sha512 += str(file)
                hashoutput_sha512 += " \n"
            if ripemd160:
                print("RIPEMD160 ", end="")
                result_ripemd160 = filehashtools.ripemd160hash(
                    os.path.join(
                        workingdir,
                        file),
                    blocksize)
                hashoutput_ripemd160 += str(result_ripemd160.upper())
                hashoutput_ripemd160 += " "
                hashoutput_ripemd160 += str(file)
                hashoutput_ripemd160 += " \n"
            if whirlpool:
                print("WHIRLPOOL ", end="")
                result_whirlpool = filehashtools.whirlpoolhash(
                    os.path.join(
                        workingdir,
                        file),
                    blocksize)
                hashoutput_whirlpool += str(result_whirlpool.upper())
                hashoutput_whirlpool += " "
                hashoutput_whirlpool += str(file)
                hashoutput_whirlpool += " \n"
            print("\n")
    with open(os.path.join(workingdir, 'all.cksum'), 'w') as target:
        if adler32:
            target.write(hashoutput_adler32 + "\n")
        if crc32:
            target.write(hashoutput_crc32 + "\n")
        if md4:
            target.write(hashoutput_md4 + "\n")
        if md5:
            target.write(hashoutput_md5 + "\n")
        if sha1:
            target.write(hashoutput_sha1 + "\n")
        if sha224:
            target.write(hashoutput_sha224 + "\n")
        if sha256:
            target.write(hashoutput_sha256 + "\n")
        if sha384:
            target.write(hashoutput_sha384 + "\n")
        if sha512:
            target.write(hashoutput_sha512 + "\n")
        if ripemd160:
            target.write(hashoutput_ripemd160 + "\n")
        if whirlpool:
            target.write(hashoutput_whirlpool + "\n")
    if any((crc32, adler32,
           md4, md5,
           sha1, sha224, sha256, sha384, sha512,
           ripemd160, whirlpool)):
        with open(os.path.join(workingdir, 'all.cksum'), 'rb+') as target:
            target.seek(-2, os.SEEK_END)  # navigate to last character
            target.truncate()  # get rid of trailing \n
    else:
        os.remove(os.path.join(workingdir, 'all.cksum'))


def gpgrunner(workingdir, keyid=None, passphrase=None):
    """
    Create ASCII-armored PGP signatures for all files in a given directory.

    :param workingdir: Path containing files you wish to verify.
    :type workingdir: str

    :param keyid: Key to use. 8-character hexadecimal, with or without 0x.
    :type keyid: str

    :param passphrase: Passphrase for given key.
    :type passphrase: str
    """
    try:
        gpg = gnupg.GPG()
    except ValueError:
        print("COULD NOT FIND GnuPG!")
        raise SystemExit
    else:
        if not keyid.startswith("0x"):
            keyid = "0x" + keyid.upper()
        for file in os.listdir(workingdir):
            if os.path.isdir(os.path.join(workingdir, file)):
                pass  # exclude folders
            else:
                print("VERIFYING:", str(file))
                try:
                    filehashtools.gpgfile(os.path.join(
                                                   workingdir,
                                                   file
                                      ),
                                      gpg,
                                      keyid=keyid,
                                      passphrase=passphrase)
                except Exception as e:
                    print("SOMETHING WENT WRONG")
                    print(str(e))
                raise SystemExit
