#!/usr/bin/env python

"""Test the compressed_file_mod module."""

import sys

import bufsock
import compressed_file_mod
import helpers


def round_trip(filename, description):
    """Test compressing and decompressing a file.  If the result is equal, the test passes."""
    compressed_file = compressed_file_mod.Compressed_file('test-file.rm-me', 'wb')
    file_ = bufsock.rawio(filename, 'r')
    data = file_.read()
    file_.close()
    compressed_file.write(data)
    compressed_file.close()

    compressed_file = compressed_file_mod.Compressed_file('test-file.rm-me', 'rb')
    decompressed_data = compressed_file.read()
    compressed_file.close()

    if data == decompressed_data:
        return True
    sys.stderr.write('%s: %s: data != decompressed_data\n' % (description, sys.argv[0]))
    return False


def hard_file_round_trip():
    """Test compressing and decompressing an already-hard file.  If the result is equal, the test passes."""
    return round_trip('hard-file', 'already-compressed data')


def soft_file_round_trip():
    """Test compressing and decompressing an easy-to-compress file.  If the result is equal, the test passes."""
    return round_trip('soft-file', 'easy-to-compress data')


def compression_type(filename, expected):
    """Compress a file.  Verify what kind of compression was used."""
    binary_expected = [helpers.string_to_binary(element) for element in expected]

    compressed_file = compressed_file_mod.Compressed_file('test-file.rm-me', 'wb')
    file_ = bufsock.rawio(filename, 'r')
    data = file_.read()
    file_.close()
    compressed_file.write(data)
    compressed_file.close()

    file2 = bufsock.bufsock(bufsock.rawio('test-file.rm-me', 'rb'))
    actual = helpers.string_to_binary(file2.readline().rstrip())
    file2.close()

    if actual in binary_expected:
        if actual != binary_expected[0]:
            sys.stderr.write('%s: Warning: Allowed compression found, but not preferred compression\n' % sys.argv[0])
        return True
    else:
        sys.stderr.write('%s: filename %s, got wrong compression type %s, binary_expected %s\n' % (
            sys.argv[0],
            filename,
            actual,
            binary_expected,
            ))
        return False


def hard_file_compression_type():
    """Make sure a hard file is stored rather than recompressed."""
    return compression_type('hard-file', ['1'])


def soft_file_compression_type():
    """Make sure a soft file is compressed rather than stored."""
    # We expect either bzip2 or xz - preferring xz over bzip2.
    return compression_type('soft-file', ['8', '5'])


def zero_length_fail():
    # pylint: disable=bare-except
    """Make sure that a 0-length file fails."""
    all_good = True

    open('zero-length', 'w').close()

    try:
        _unused = compressed_file_mod.Compressed_file('zero-length', 'rb')
        helpers.make_used(_unused)
    except ValueError:
        pass
    except Exception:
        sys.stderr.write('%s: zero_length_fail: Got other exception on zero-length file\n' % sys.argv[0])
        all_good = False
    else:
        sys.stderr.write('%s: zero_length_fail: Did not get an exception\n' % sys.argv[0])
        all_good = False

    return all_good


def zero_length_succeed():
    # pylint: disable=bare-except
    """Make sure that reading an empty file gives an empty string."""
    all_good = True

    open('zero-length', 'w').close()

    try:
        compressed_file = compressed_file_mod.Compressed_file('zero-length', 'rb', zero_length_ok=True)
    except ValueError:
        sys.stderr.write('%s: Compressed_file raised ValueError\n' % sys.argv[0])
        all_good = False
    except Exception:
        sys.stderr.write('%s: Compressed_file raised other exception\n' % sys.argv[0])
        all_good = False
    else:
        data = compressed_file.read()
        compressed_file.close()

        if data != helpers.empty_bytes:
            sys.stderr.write('%s: Compressed_file did not return empty bytes\n' % sys.argv[0])
            all_good = False

    return all_good


def main():
    """Start testing."""
    all_good = True

    all_good &= hard_file_round_trip()
    all_good &= soft_file_round_trip()
    all_good &= hard_file_compression_type()
    all_good &= soft_file_compression_type()
    all_good &= zero_length_fail()
    all_good &= zero_length_succeed()

    if all_good:
        sys.stderr.write('%s: All tests passed\n' % sys.argv[0])
        sys.exit(0)
    else:
        sys.stderr.write('%s: One or more tests failed\n' % sys.argv[0])
        sys.exit(1)


main()