#!/usr/bin/env python

'''Test the compressed_string_mod module'''

from __future__ import with_statement

import os
import sys

import bufsock
import python2x3
import constants_mod
import compressed_string_mod

def round_trip(filename, description):
    '''Test compressing and decompressing a string.  If the result is equal, the test passes'''

    input_file = os.open(filename, os.O_RDONLY)
    input_bs = bufsock.bufsock(input_file)
    input_data = input_bs.read()
    input_bs.close()

    #print('round_trip: type(input_data): %s' % type(input_data))
    #print('round_trip: len(input_data): %s' % len(input_data))

    compressed_data = compressed_string_mod.compress_string(input_data)
    #print('round_trip: type(compressed_data): %s' % type(compressed_data))
    #print('round_trip: len(compressed_data): %s' % len(compressed_data))

    decompressed_data = compressed_string_mod.decompress_string(compressed_data)
    #print('round_trip: type(decompressed_data): %s' % type(decompressed_data))
    #print('round_trip: len(decompressed_data): %s' % len(decompressed_data))

    if input_data == decompressed_data:
        return True
    else:
        sys.stderr.write('%s: %s: input_data (%d) != decompressed_data (%d) - compressed_data (%d)\n' % (
            description,
            sys.argv[0],
            len(input_data),
            len(decompressed_data),
            len(compressed_data),
            ))
        return False

def hard_string_round_trip():
    '''Test compressing and decompressing an already-hard string.  If the result is equal, the test passes'''

    return round_trip('hard-file', 'already-compressed data')

def soft_string_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'''
    ints_expected = [python2x3.string_to_binary(element)[0] for element in expected]

    file_ = bufsock.rawio(filename, 'r')
    data = file_.read()
    file_.close()

    compressed_data = compressed_string_mod.compress_string(data)

    actual = compressed_data[0]
    # FIXME: This assumes that constants_mod.Constants.b_newline is a single character - probably
    # pretty safe assumption, but still, it's an assumption
    if compressed_data[1] == constants_mod.Constants.b_newline[0]:
        pass
    else:
        print('compressed_data[1]: %s, constants_mod.Constants.b_newline[0]: %s\n' % (
            compressed_data[1],
            constants_mod.Constants.b_newline[0],
            ))
        sys.exit(1)

    if actual in ints_expected:
        if actual != ints_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, ints_expected %s\n' % (
            sys.argv[0],
            filename,
            actual,
            ints_expected,
            ))
        return False

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

def soft_string_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', ['7', '5'])

def main():
    '''Main function'''
    all_good = True

    all_good &= hard_string_round_trip()
    all_good &= soft_string_round_trip()
    all_good &= hard_string_compression_type()
    all_good &= soft_string_compression_type()

    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()