import FreeCAD as App
import json
import os




def has_active_document():
    doc = App.activeDocument()
    if not doc:
        App.Console.PrintError("Нет активного документа в FreeCAD.\n")
        return False
    return True

def get_assembly_settings_folder():
    if not has_active_document():
        return False

    doc = App.activeDocument()
    assembly_settings_folder = None
    for obj in doc.Objects:
        if obj.Name == "Assembly_Settings":
            assembly_settings_folder = obj
            break
    if not assembly_settings_folder:
        assembly_settings_folder = doc.addObject("App::DocumentObjectGroup", "Assembly_Settings")
    
    return assembly_settings_folder
        




#Создаем объект, описывающий крепежные элементы
#Стоит отметить, что структура крепежа может быть сложнее, чем просто винт. В будущем стоит придумать, как отразить эту структуру, если это необходимо

def create_fastener_set():
    doc = App.activeDocument()
    assembly_settings_folder = get_assembly_settings_folder()

    fastener_set = doc.addObject("Part::FeaturePython", "Fastener_Set")
    fastener_set.addProperty("App::PropertyString", "Type", 'Asm_Settings').Type = 'fastener_set'
    fastener_set.addProperty("App::PropertyLink", "Parent", 'Asm_Settings')
    fastener_set.addProperty("App::PropertyLink", "Child", 'Asm_Settings')
    fastener_set.addProperty("App::PropertyLinkList", "Fasteners", 'Asm_Settings')

    assembly_settings_folder.addObject(fastener_set)


#Жесткая последовательность для двух деталей
def create_assembly_sequence():
    doc = App.activeDocument()
    assembly_settings_folder = get_assembly_settings_folder()

    assembly_sequence = doc.addObject("Part::FeaturePython", "Assembly_Sequence")
    assembly_sequence.addProperty("App::PropertyString", "Type", 'Asm_Settings').Type = 'asm_sequence'
    assembly_sequence.addProperty("App::PropertyLink", "Parent", 'Asm_Settings')
    assembly_sequence.addProperty("App::PropertyLink", "Child", 'Asm_Settings')

    assembly_settings_folder.addObject(assembly_sequence)



#Допустимый зазор для группы элементов, при котором будут распознаваться контакты с окружающими деталями
def create_clearance_constraint(max_clearance = 1.0):
    doc = App.activeDocument()
    assembly_settings_folder = get_assembly_settings_folder()
    

    clearance_constraint = doc.addObject("Part::FeaturePython", "Clearance_Constraint")
    clearance_constraint.addProperty("App::PropertyLinkList", "PartName", 'Asm_Settings')
    clearance_constraint.addProperty("App::PropertyString", "Type", 'Asm_Settings').Type = 'clearance'
    clearance_constraint.addProperty("App::PropertyFloat", "MaxClearance", 'Asm_Settings').MaxClearance = max_clearance

    assembly_settings_folder.addObject(clearance_constraint)

def create_assembly_parameters():
    doc = App.activeDocument()
    assembly_settings_folder = get_assembly_settings_folder()

    assembly_parameters = doc.addObject("Part::FeaturePython", "Assembly_Parameters")
    assembly_parameters.addProperty("App::PropertyFloat", "Subassembly_Size", 'Asm_Settings')
    assembly_parameters.addProperty("App::PropertyLink", "Subassembly_Mass", 'Asm_Settings')
    assembly_parameters.addProperty("App::PropertyBool", "Materials_Together", 'Asm_Settings')
    assembly_parameters.addProperty("App::PropertyFloat", "Total_Clearance")

    assembly_settings_folder.addObject(assembly_parameters)



#экспорт всех заданных настроек в общий файл json
def export_assembly_settings():
    doc = App.activeDocument()
    if not doc:
        return

    assembly_settings_folder = None
    for obj in doc.Objects:
        if obj.Name == "Assembly_Settings":
            assembly_settings_folder = obj
            break

    if not assembly_settings_folder:
        return

    data = []
    for obj in assembly_settings_folder.Group:
        if hasattr(obj, "Type"):
            obj_dict = {"Name": obj.Name}
            if obj.Type == "fastener_set":
                fasteners = [part.Label for part in obj.Fasteners]
                obj_dict.update({
                    "Type": "fastener_set",
                    "Parent": obj.Parent.Label,
                    "Child": obj.Child.Label,
                    "Fasteners": fasteners
                })
            elif obj.Type == "asm_sequence":
                obj_dict.update({
                    "Type": "asm_sequence",
                    "Parent": obj.Parent.Label,
                    "Child": obj.Child.Label 
                })
            elif obj.Type == "clearance":
                partnames = [part.Label for part in obj.PartName]
                obj_dict.update({
                    "Type": "clearance",
                    "PartName": partnames,
                    "MaxClearance": obj.MaxClearance
                })
            data.append(obj_dict)

    save_dir = os.path.dirname(doc.FileName)
    save_path = os.path.join(save_dir, "assembly_settings_" + App.ActiveDocument.Label + ".json")
    with open(save_path, "w") as f:
        json.dump(data, f, indent=4)

#для работы с данными как с переменной
def collect_assembly_settings():
    doc = App.activeDocument()
    if not doc:
        return None

    assembly_settings_folder = None
    for obj in doc.Objects:
        if obj.Name == "Assembly_Settings":
            assembly_settings_folder = obj
            break

    if not assembly_settings_folder:
        return None

    assembly_settings = []
    for obj in assembly_settings_folder.Group:
        if hasattr(obj, "Type"):
            obj_dict = {"Name": obj.Name}
            if obj.Type == "fastener_set":
                fasteners = [part.Label for part in obj.Fasteners]
                obj_dict.update({
                    "Type": "fastener_set",
                    "Parent": obj.Parent.Label,
                    "Child": obj.Child.Label,
                    "Fasteners": fasteners
                })
            elif obj.Type == "asm_sequence":
                obj_dict.update({
                    "Type": "asm_sequence",
                    "Parent": obj.Parent.Label,
                    "Child": obj.Child.Label 
                })
            elif obj.Type == "clearance":
                partnames = [part.Label for part in obj.PartName]
                obj_dict.update({
                    "Type": "clearance",
                    "PartName": partnames,
                    "MaxClearance": obj.MaxClearance
                })
            assembly_settings.append(obj_dict)

    return assembly_settings

# create_fastener_set()
# create_assembly_sequence()
# create_clearance_constraint()
# export_assembly_settings()