#!/usr/bin/env python

# Runs a subsetting test suite. Compares the results of subsetting via harfbuz
# to subsetting via fonttools.

from __future__ import print_function

import io
from difflib import unified_diff
import os
import re
import subprocess
import sys
import tempfile

from subset_test_suite import SubsetTestSuite


def cmd(command):
	p = subprocess.Popen (
		command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
	p.wait ()
	print (p.stderr.read (), end="") # file=sys.stderr
	return p.stdout.read (), p.returncode

def read_binary(file_path):
	with open(file_path, 'rb') as f:
		return f.read()

def fail_test(test, cli_args, message):
	print ('ERROR: %s' % message)
	print ('Test State:')
	print ('  test.font_path    %s' % os.path.abspath(test.font_path))
	print ('  test.profile_path %s' % os.path.abspath(test.profile_path))
	print ('  test.unicodes	    %s' % test.unicodes())
	expected_file = os.path.join(test_suite.get_output_directory(),
				     test.get_font_name())
	print ('  expected_file	    %s' % os.path.abspath(expected_file))
	return 1

def run_test(test):
	out_file = os.path.join(tempfile.mkdtemp(), test.get_font_name() + '-subset.ttf')
	cli_args = [hb_subset,
		    "--font-file=" + test.font_path,
		    "--output-file=" + out_file,
		    "--unicodes=%s" % test.unicodes()]
	print (' '.join(cli_args))
	_, return_code = cmd(cli_args)

	if return_code:
		return fail_test(test, cli_args, "%s returned %d" % (' '.join(cli_args), return_code))

	expected_ttx, return_code = run_ttx(os.path.join(test_suite.get_output_directory(),
					    test.get_font_name()))
	if return_code:
		return fail_test(test, cli_args, "ttx (expected) returned %d" % (return_code))

	actual_ttx, return_code = run_ttx(out_file)
	if return_code:
		return fail_test(test, cli_args, "ttx (actual) returned %d" % (return_code))

	expected_ttx = strip_check_sum (expected_ttx)
	actual_ttx = strip_check_sum (actual_ttx)

	if not actual_ttx == expected_ttx:
		for line in unified_diff(expected_ttx.splitlines(1), actual_ttx.splitlines(1)):
			sys.stdout.write(line)
		sys.stdout.flush()
		return fail_test(test, cli_args, 'ttx for expected and actual does not match.')

	return 0

def run_ttx(file):
	cli_args = ["ttx",
		    "-o-",
		    file]
	return cmd(cli_args)

def strip_check_sum (ttx_string):
	return re.sub ('checkSumAdjustment value=["]0x([0-9a-fA-F])+["]',
                       'checkSumAdjustment value="0x00000000"',
		       ttx_string, count=1)

args = sys.argv[1:]
if not args or sys.argv[1].find('hb-subset') == -1 or not os.path.exists (sys.argv[1]):
	print ("First argument does not seem to point to usable hb-subset.")
	sys.exit (1)
hb_subset, args = args[0], args[1:]

if not len(args):
	print ("No tests supplied.")
	sys.exit (1)

_, returncode = cmd(["which", "ttx"])
if returncode:
	print("TTX is not present, skipping test.")
	sys.exit (77)

fails = 0
for path in args:
	with io.open(path, mode="r", encoding="utf-8") as f:
		print ("Running tests in " + path)
		test_suite = SubsetTestSuite(path, f.read())
		for test in test_suite.tests():
			fails += run_test(test)

if fails != 0:
	print (str (fails) + " test(s) failed.")
	sys.exit(1)
else:
	print ("All tests passed.")
