# Copyright 2024 Michael Becker  <alcexhim@gmail.com>
# 
# 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
# 
#     https://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.

from glob import glob

from mocha.library.parser import YAMLLibraryParser

from mocha.library.manager import MochaLibraryManager, MemoryLibraryManager

import os, sys

class Yaml2Mcl:

	def __init__(self):

		pass

	def start(self):

		

		args = sys.argv[1:]
		# args = [ '-o', '/tmp/net.alcetech.Mocha.System.mcl', '/home/beckermj/Documents/Projects/mochapowered/mocha-dotnet/mocha-common/mocha-common/data/libraries/yaml/net.alcetech.Mocha.System' ]
		# args = [ "--reference", "/home/beckermj/Documents/Projects/mochapowered/mocha-dotnet/mocha-common/mocha-common/output/net.alcetech.Mocha.System.mcl", '-o', '/tmp/net.alcetech.Mocha.Web.mcl', '/home/beckermj/Documents/Projects/mochapowered/mocha-dotnet/mocha-common/mocha-common/data/libraries/yaml/net.alcetech.Mocha.Web' ]

		# !! FIXME !! the instance key is probably not in the cache because the 'class' template is not loaded from the YAML so it doesn't know what to do

		filenames = [ ]
		outputFileName = ""
		exportEntitiesFileName = None
		libraryReferences = [ ]
		manager = MemoryLibraryManager()

		while (len(args) > 0):
			# print (args[0])
			if args[0] == "-o" or args[0] == "--output":
				outputFileName = args[1]
				args = args[2:]
			elif args[0] == "--strip-debug-information":
				manager.enable_debug_information = False
				args = args[1:]
			elif args[0] == "--export-entities":
				exportEntitiesFileName = ""
				args = args[1:]
			elif args[0].startswith("--export-entities="):
				exportEntitiesFileName = args[0].split('=', 2)[1]
				args = args[1:]
			elif args[0] == "--reference":
				libraryReferences.append(args[1])
				args = args[2:]
			else:
				filenames.append(args[0])
				args = args[1:]


		print ("Mocha YAML to Mocha Class Library Compiler")
		print ("Version 1.0")
		print ("")

		print ("refs: ")
		print (libraryReferences)
		print ("")

		print (filenames)
		print ("output to: " + outputFileName)

		yl = YAMLLibraryParser(manager)

		# before we load any files, load entity definitions from referenced libraries
		libraryRefGuids = [ ]

		for libraryRef in libraryReferences:
			from mocha.library.mcx.dataformats import McxDataFormat
			from mocha.library.mcx.objectmodels import McxObjectModel
			
			om = McxObjectModel()
			df = McxDataFormat()
			f = open(libraryRef, 'rb')
			df.load_internal(om, f)
			f.close()

			libraryRefGuids.append(om.get_guid())

			print ("loading entity definitions from library reference '" + libraryRef + "'")

			for (k, v) in om.get_entity_definitions():
				manager.register_entity_reference(k, v, libraryRef, True)
			
			print ("loading GUID table from library reference '" + libraryRef + "'")

			for inst in om.get_instances():
				manager.add_instance_ref(inst.get_class_global_identifier(), inst.get_instance_global_identifier(), inst.get_class_index(), inst.get_instance_index())


			tdfs = om.get_template_definitions()
			for key in tdfs:
				yl.register_template(key, tdfs[key], True)
			
		manager.library_reference_guids = libraryRefGuids

		filenames2 = [ ]

		for filename in filenames:
			if not os.path.isdir(filename):
				filenames2.append(filename)
				continue

			yaml_files = sorted(glob(filename + "/**/*.yaml", recursive=True))
			if len(yaml_files) == 0:
				print ("no YAML files found ; does the path exist?")
				return 3
			
			# first, load the entity defs
			for yaml_file in yaml_files:
				yl.load_entity_definitions_from_file(yaml_file)

		#try:
			# then, load instance definitions (also loads sugar elements into memory for later use)
			for yaml_file in yaml_files:
				yl.load_instances_from_file(yaml_file)
					
			# finally, apply syntactic sugar
			yl.apply_sugar()

			manager.filename = outputFileName
			manager.parser = yl
			manager.commit()

			if not exportEntitiesFileName is None:
				if exportEntitiesFileName == "":
					exportEntitiesFileName = "entities.cs"
				
				print("export entities to file: '" + exportEntitiesFileName + "'")
				manager.save_entities_to_file(exportEntitiesFileName, outputFileName)

		if len(filenames2) > 0:
			yaml_files = filenames2

			# first, load the entity defs
			for yaml_file in yaml_files:
				yl.load_entity_definitions_from_file(yaml_file)

		#try:
			# then, load instance definitions (also loads sugar elements into memory for later use)
			for yaml_file in yaml_files:
				yl.load_instances_from_file(yaml_file)
					
			# finally, apply syntactic sugar
			yl.apply_sugar()

			manager.filename = outputFileName
			manager.parser = yl
			manager.commit()

			if not exportEntitiesFileName is None:
				if exportEntitiesFileName == "":
					exportEntitiesFileName = "entities.cs"
				
				print("export entities to file: '" + exportEntitiesFileName + "'")
				manager.save_entities_to_file(exportEntitiesFileName, outputFileName)
				
				
		return True

		#except NameError as ex:

			# print (ex)

			# rgx = "&(.*);"
			
			# # go through and get all entity references across all files
			# import re

			# stuff = []
			
			# for yaml_file in yaml_files:
			# 	f = open(yaml_file, "r")
			# 	text = f.read()
			# 	matches = re.findall(rgx, text)
			# 	for match in matches:
			# 		stuff.append(match)
			# 	f.close()

			# missingEntities = []
			# for stuf in stuff:
			# 	if not stuf in manager.entityReferences:
			# 		if not stuf in missingEntities:
			# 			missingEntities.append(stuf)

			# if len(missingEntities) > 0:
			# 	print("\nNOTE: there were undefined referenced entities:\n")
			# 	for missingEntity in missingEntities:
			# 		print("\t" + missingEntity)
			# 	print("\n")

			# return False


if __name__ == "__main__":

	app = Yaml2Mcl()
	app.start()