'''
Эта штука создается с целью проводить все необходимые проверки и манипуляции при движении моделей
по пайплайну

Планируемые фичи:
    1. Материалы:
        1.1 Проверка на уникальность
        1.2 Проверка на повторяемость
        1.3 Проверки на соответствие материала требованиям
        1.4 Изменение цветов деталей по факту назначения материалов
        1.5 Расчет массы по плотностям деталей и прописывание ее в свойствах детали
        1.6 Указание наименования материала в свойствах детали
        
    2. Вспомогательные обьекты и тела:
        2.1. Вспомогательные обьекты имеют отметки о своем статусе
        2.2. Несолиды имеют пометку несолидовости
        2.3 Детали без материалов должны быть с материалами
        
    3. [на будущее] Проверка существования разметки
    
    4. Дополнение информации в бом-лист (это нужно засунуть в бом, а не сюда)
    


'''

import FreeCAD as App
import FreeCADGui as Gui
from helper.is_solid import is_object_solid
import json

doc = App.ActiveDocument

#0 Проверка существования директорий
#должны быть директории на материалы, на технологические операции, на вспомогательные обьекты
#если у нас есть директория "анализ" от Fem, то мы переименуем ее в свою директорию и сделаем ей пометку. 
#если мы находим материалы в дереве, которые не относятся к этой директории, мы должны засунуть их в нашу директорию
#если материалов нет, мы должны указать, что их нет


def materialExistenceCheck(doc):
    
    # if "Materials" not in doc.Objects:
    if doc.getObjectsByLabel('Materials') == 0:    
        material_group = doc.addObject("App::DocumentObjectGroup", "Materials")
        App.Console.PrintMessage("Директория материалов не обнаружена и была создана вновь\n")
        
        
    else:
        material_group = doc.getObject("Materials")
    
    fem_materials = [obj for obj in doc.Objects if (hasattr(obj, 'Proxy') and hasattr(obj.Proxy, 'Type') and obj.Proxy.Type == 'Fem::MaterialCommon')]
    
    if len(fem_materials) > 0:
        for material in fem_materials:
            material_group.addObject(material)
        print('Материалы успешно скомпонованы')    
    else:
    
        App.Console.PrintMessage("FEM-материалы не заданы. Укажите FEM-материалы и произведите проверку\n")
    Gui.updateGui()
    
    return material_group, fem_materials #шоб не пропадало зазря
    
    
[material_group, fem_materials ] =  materialExistenceCheck(doc) # укомпоновали материалы


#проверим, что материалы правильно описаны:
# Открываем файл JSON с требованиями и загружаем его содержимое
# with open('material_requirements.json', 'r') as f:
#     material_requirements = json.load(f)
material_requirements = ["Density",
"DiffuseColor",
"EmissiveColor"
]




def material_isCorrect(fem_materials, material_requirements):
    femmat_trobles = {}
    for femmat in fem_materials:
        for req in material_requirements:
            if not ( req in femmat.Material and femmat.Material[req]):
                if femmat in femmat_trobles:
                    femmat_trobles[femmat].append(req)
                else:
                    femmat_trobles[femmat] = [req]             
   
    print(femmat_trobles)
                 

material_isCorrect(fem_materials, material_requirements)


#1
#1.1 Проверка на уникальность

#присвоим каждому телу имя материала и значение плотности

def matProperties2bodies(doc, fem_materials):
    #проходимся по всем материалам и присваиваем деталюхам параметры
    #нужно кстати еще цвет им переназначить
    for femmat in fem_materials:
        
        body = doc.getObject(femmat.References[0][0].Name).Label #вот эта вот абоба добывает нам тело из перечисления
        #в это тело нам надо добавить два свойства
        
        #нужно проверить, есть ли материальные свойства у тела и, если нет, добавить их
        #в следующей серии будем проверять все тела, есть ли у них материал
        if 'MaterialName' in body.PropertiesList:
            if body.getPropertyByName('MaterialName') != femmat.Material['CardName']: #если не совпадает
                print('ВНИМАНИЕ! Тело ' + body.Label + ' имеет переназначение материалов. Проверьте и укажите один (1) правильный материал!')
                body.setProperty('MaterialName', femmat.Material['CardName']) #пусть перепишется на новый
                body.setProperty('Density', femmat.Material['Density']) #плотность
        else:
            body.addObjectProperty('MaterialName', femmat.Material['CardName']) #добавляем название материала
            body.addObjectProperty('Density', femmat.Material['Density']) #добавляем плотность
        
        
        #считаем массу деталюх
        density, unit = parse_values(femmat.Material['Density'])
        volume = body.Shape.Volume
        body_mass = volume * density
        body.addObjectProperty('Mass', body_mass) #масса деталюхи
        
def bodyWithoutMaterialsCheck(doc):
    objs = doc.Objects
    for obj in objs:
        #проверка на солидовость
        if (is_object_solid(obj) and ('MaterialName' not in obj.PropertiesList)):
            print('Деталь ' + obj.Label + 'не имеет назначения материала')
            
matProperties2bodies(doc, fem_materials)        
bodyWithoutMaterialsCheck(doc)

#после выполнения предыдущей функции у нас появились деталюхи с обозначениями материалов
#все деталюхи без этой позиции нужно как-то выделить, а 
    
#гпт предлагает парсить значение единиц измерения
#я с ним соглашусь
        
def parse_values(value_str):
    value = ""
    unit = ""
    
    # Проверяем каждый символ в строке плотности
    for char in value_str:
        if char.isdigit() or char == ".":
            # Символ является цифрой или точкой - добавляем его к числу
            value += char
        else:
            # Символ не является цифрой или точкой - считаем его частью единицы измерения
            unit += char
    
    # Преобразуем значение плотности в число
    density = float(value)
    
    return value, unit


#todo:
# сделать проверку на солидовые тела
#укомпоновать все вспомогательные обьекты в отдельную штуку
#wip   

#подготавливаем действия и состояния для PDDL
# 