from pathlib import Path
import os
import sys

sys.path.append(os.path.join(os.path.dirname(__file__), 'utils'))
import vspt_freecad

import FreeCAD as App
import Import
import ImportGui
import TechDrawGui

project_folder = os.getcwd()
output_folder = project_folder + '/dist/STEP'
assemblies_output_folder = project_folder + '/dist/FCStd'
drawings_output_folder = project_folder + '/dist/PDF'

def convert_file(file_name, output_format):
	doc = App.open(project_folder + '/' + file_name)
	
	root_objects = []
	main_object = None
	
	#print("document: " + doc.Name)
	for obj in doc.Objects:
		if len(obj.Parents) == 0:
			#print(obj.Label)
			root_objects.append(obj)
			if obj.Label == doc.Name or obj.Label == doc.Name + ' (experimental)':
				main_object = obj
	
	if main_object is None and len(root_objects) == 1:
		main_object = root_objects[0]
	
	if main_object is None:
		raise Exception("Can't find main object in file " + file_name + " (found " + str(len(root_objects)) + " root object(s), none named like the document " + doc.Name + ")")
		
	if 'experimental' in main_object.Label or 'expérimental' in main_object.Label:
		print('Document ' + doc.Name + ' is marked as experimental and will be ignored')
		vspt_freecad.close_all_docs()
		return
		
	secondary_objects = []
	code_obj = doc.getObjectsByLabel('Code_Tube_Draft')
	if len(code_obj) == 1:
		code_obj = code_obj[0]
		#code_obj.Label = 'Code_Tube'
		#secondary_objects.append(code_obj)
		
		# engrave code on tube
		code_pocket = main_object.newObjectAt('PartDesign::Pocket','Pocket', [code_obj])
		code_pocket.Profile = code_obj
		code_pocket.Length = 0.2
		code_pocket.recompute()
		main_object.recompute()
		
	if len(secondary_objects) > 0:
		group = doc.addObject('App::Part', 'Groupe')
		group.addObject(main_object)
		for obj in secondary_objects:
			group.addObject(obj)
		main_object = group
		
	output_path = output_folder + '/' + os.path.dirname(file_name) + '/' + Path(file_name).stem + '.' + output_format
	output_dir = os.path.dirname(output_path)
	if not os.path.exists(output_dir):
		os.makedirs(output_dir)
	
	if output_format.lower() == 'stpz':
		import stepZ
		stepZ.export([main_object], output_path)
	else:
		Import.export([main_object], output_path)
	
	# Export 2D drawing
	page_name = doc.Name + '_Drawing'
	drawing_page = doc.getObject(page_name)
	if drawing_page is not None:
		drawing_output_path = drawings_output_folder + '/' + os.path.dirname(file_name) + '/' + Path(file_name).stem + '.pdf'
		drawing_output_dir = os.path.dirname(drawing_output_path)
		if not os.path.exists(drawing_output_dir):
			os.makedirs(drawing_output_dir)
		drawing_page.ViewObject.Visibility = True
		TechDrawGui.export([drawing_page], drawing_output_path)
	
	vspt_freecad.close_all_docs()

def export_assembly(doc, file_name, output_format):
	root_objects = []
	main_object = None
	
	# remove all objects that are not visible, or not in the TypeId whitelist, because we don't want to export those
	need_check_objects = True
	while need_check_objects:
		need_check_objects = False
		for obj in doc.Objects:
			if not obj.Visibility or obj.TypeId not in ['Part::Feature', 'Part::FeaturePython', 'PartDesign::Body', 'Part::Mirroring', 'Part::Cut', 'Part::Part2DObjectPython', 'Part::MultiFuse', 'Part::Loft', 'Part::Torus', 'Part::Cylinder', 'App::DocumentObjectGroup', 'App::Part', 'App::Link']:
				#print('removing ' + obj.Name + ' ('+obj.Label+')')
				doc.removeObject(obj.Name)
				need_check_objects = True
				break
	
	for obj in doc.Objects:
		if len(obj.Parents) == 0:
			#print(obj.Label)
			root_objects.append(obj)
			if obj.Label == doc.Name:
				main_object = obj
	
	if main_object is None and len(root_objects) == 1:
		main_object = root_objects[0]
	
	if main_object is None:
		raise Exception("Can't find main assembly in file " + file_name + " (found " + str(len(root_objects)) + " root object(s), none named like the document " + doc.Name + ")")
		
	output_path = output_folder + '/' + os.path.dirname(file_name) + '/' + Path(file_name).stem + '.' + output_format
	output_dir = os.path.dirname(output_path)
	if not os.path.exists(output_dir):
		os.makedirs(output_dir)
	
	if output_format.lower() == 'stpz':
		import stepZ
		stepZ.export([main_object], output_path)
	else:
		ImportGui.export([main_object], output_path)
	
def convert_assembly(file_name, output_format):
	print("Exporting assembly " + file_name + "...")
	doc = App.open(project_folder + '/' + file_name)
	export_assembly(doc, file_name, output_format)
	vspt_freecad.close_all_docs()

def export_configuration(file_name, config_name, output_filename, output_format):
	print('Generating assembly for configuration '+config_name+'...')
	
	doc = App.open(project_folder + '/' + file_name)
	
	Gui.Selection.clearSelection()
	Gui.Selection.addSelection('vheliotech','Model','Configurations.'+doc.getObjectsByLabel(config_name)[0].Name+'.')
	Gui.runCommand('Asm4_applyConfiguration')
	Gui.Selection.clearSelection()
	
	export_assembly(doc, output_filename, output_format)
	
	#doc.saveAs(assemblies_output_folder + '/' + output_filename + '.FCStd')
	
	vspt_freecad.close_all_docs()

try:
	folders = [
		'chaudronnerie',
		'tubes'
	]

	for folder in folders:
		files = os.listdir(project_folder + '/' + folder)
		for source_file in files:
			if not source_file.endswith('.FCStd'): continue
			source_path = folder + '/' + source_file
			print(source_path)
			convert_file(source_path, 'step')

	#convert_assembly('vheliotech.FCStd', 'step')

	export_configuration('vheliotech.FCStd', 'Config_Integrale', 'vheliotech-integral', 'step')
	export_configuration('vheliotech.FCStd', 'Config_Solaire', 'vheliotech-solaire', 'step')
	export_configuration('vheliotech.FCStd', 'Config_Motorisee', 'vheliotech-motorise', 'step')
	export_configuration('vheliotech.FCStd', 'Config_Basique', 'vheliotech-basique', 'step')
	
except Exception as e:
	print(e)

# exit FreeCAD
vspt_freecad.close_all_docs()
FreeCADGui.getMainWindow().close()