# -*- coding: utf-8 -*-

#-------------------------------------------------------------------------
# drawElements Quality Program utilities
# --------------------------------------
#
# Copyright 2019 The Khronos Group Inc.
# Copyright 2015 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#-------------------------------------------------------------------------

import sys
from functools import partial
from argparse import ArgumentParser
from common import getChangedFiles, getAllProjectFiles, isTextFile

EXCLUSION_LIST = [
	"/doc/testspecs/VK/apitests.adoc",
	"/targets/default/FindWayland.cmake",
]

def checkEnds(line, ends):
	return any(line.endswith(end) for end in ends)

def hexDumpFromFile(filename, position, size):
	print("Invalid symbol(s) at offset %x (%i), byte number: %i" % (position, position, size))
	columnWidth = 32
	size += position % columnWidth
	position = columnWidth * int(position / columnWidth)
	size = columnWidth * int((size + columnWidth - 1) / columnWidth)

	f = open(filename, 'rb')
	f.seek(position)

	out1 = ""
	out2 = ""
	numBytes = 0
	while numBytes < size:
		if numBytes % columnWidth == 0:
			if len(out1) != 0:
				print(out1 + "	" + out2)
				out1 = ""
				out2 = ""
			out1 += "%0.8X: " % + (position + numBytes)

		byte = f.read(1)
		if (byte == None):
			break;

		if (sys.version_info < (3, 0)):
			byte = int(ord(byte[0]))
		else:
			byte = int(byte[0])

		numBytes += 1

		out1 += "%0.2X " % byte
		if (byte >= 32 and byte <=127):
			out2 += chr(byte)
		else:
			out2 += '.'

	if len(out1) != 0:
		print(out1 + "	" + out2)

	f.close()

def SearchInvalidSymbols (filename):
	start = None
	end = None
	with open(filename, 'rb') as file:
		for byte in iter(partial(file.read, 1), b''):
			if (sys.version_info < (3, 0)):
				byte = int(ord(byte[0]))
			else:
				byte = int(byte[0])
			if (byte > 0x7F):
				if start == None:
					start = file.tell()
			else:
				if start != None:
					end = file.tell()
			if end != None:
				hexDumpFromFile(filename, start, end - start)
				start = None
				end = None
		if start != None:
			file.seek(0, 2) # Seek to end of file
			end = file.tell()
			hexDumpFromFile(filename, start, end - start)

def checkFileEncoding (filename):
	generalEncoding = "ascii"
	file = None
	error = False
	try:
		if (sys.version_info < (3, 0)):
			file = open(filename, 'rt')
			for line in file:
				line.decode(generalEncoding)
		else:
			file = open(filename, 'rt', encoding=generalEncoding)
			for bytes in iter(partial(file.read, 1024 * 1024), ''):
				pass
	except UnicodeDecodeError as e:
		if not checkEnds(filename.replace("\\", "/"), EXCLUSION_LIST):
			error = True
			print("")
			print("Unicode error in file: %s (%s)" % (filename, e))
			SearchInvalidSymbols(filename)
	finally:
		if file != None:
			file.close()

	return not error

def checkEncoding (files):
	error = False
	for file in files:
		if isTextFile(file):
			if not checkFileEncoding(file):
				error = True

	return not error

if __name__ == "__main__":
	parser = ArgumentParser()
	parser.add_argument("-e", "--only-errors",  action="store_true", dest="onlyErrors",   default=False, help="Print only on error")
	parser.add_argument("-i", "--only-changed", action="store_true", dest="useGitIndex",  default=False, help="Check only modified files. Uses git.")

	args = parser.parse_args()

	if args.useGitIndex:
		files = getChangedFiles()
	else:
		files = getAllProjectFiles()

	error = not checkEncoding(files)

	if error:
		print("One or more checks failed")
		sys.exit(1)
	if not args.onlyErrors:
		print("All checks passed")