import FreeCAD as App
import FreeCADGui as Gui





#функции для создания обьектов PDDL

def add_types():
    doc = App.ActiveDocument
    types = doc.addObject('App::FeaturePython', 'Types')
    types.addProperty("App::PropertyString", 'PDDL', 'PDDL').PDDL = 'PDDL'
    types.addProperty("App::PropertyString", 'Type', 'PDDL').Type = 'Types'
    types.addProperty("App::PropertyStringList", 'Types', 'PDDL')

    print('Types of objects added successfully')
    return(types)
#слишком много types
    
def add_parameters():
    doc = App.ActiveDocument
    params = doc.addObject('App::FeaturePython', 'Parameters')
    params.addProperty("App::PropertyString", 'PDDL', 'PDDL').PDDL = 'PDDL'
    params.addProperty("App::PropertyString", 'Type', 'PDDL').Type = 'Parameters'    
    params.addProperty('App::PropertyPythonObject', 'Parameters','PDDl')

    print('Domain parameters added successfully')
    return(params)

def add_action():
    doc = App.ActiveDocument

    name = input('Название действия:')
    action = doc.addObject('App::FeaturePython', str(name))
    action.addProperty("App::PropertyString", 'PDDL', 'PDDL').PDDL = 'PDDL'
    action.addProperty("App::PropertyString", 'Type', 'PDDL').Type = 'Action'
    action.addProperty("App::PropertyStringList", 'Parameters', 'PDDL')
    action.addProperty("App::PropertyStringList", 'Conditions', 'PDDL')
    action.addProperty("App::PropertyStringList", 'Effects', 'PDDL')
    sortEntity(action)
    print('Action ' + name + 'added successfully')
    return(action)
    
    
def add_predicate():
    doc = App.ActiveDocument

    name = input('Название предиката:')
    parms = input('Переменные')
    predicate = doc.addObject('App::FeaturePython', str(name))
    predicate.addProperty("App::PropertyString", 'PDDL', 'PDDL').PDDL = 'PDDL'
    predicate.addProperty("App::PropertyString", 'Type', 'PDDL').Type = 'Predicate'
    # predicate.addProperty("App::PropertyStringList", 'Name', 'PDDL')
    predicate.addProperty("App::PropertyStringList", 'Parameters', 'PDDL').Parameters = parms
    sortEntity(predicate)
    print('Predicate ' + name + 'added successfully')
    return(predicate)
    
    
def add_durative_action():
    doc = App.ActiveDocument
    name = input('Название действия:')
    action = doc.addObject('App::FeaturePython', str(name))
    action.addProperty("App::PropertyString", 'PDDL', 'PDDL').PDDL = 'PDDL'
    action.addProperty("App::PropertyString", 'Type', 'PDDL').Type = 'DurativeAction'
    action.addProperty("App::PropertyStringList", 'Parameters', 'PDDL')
    action.addProperty("App::PropertyStringList", 'Conditions', 'PDDL')
    action.addProperty("App::PropertyStringList", 'Effects', 'PDDL')
    action.addProperty('App::PropertyString', 'Duration', 'PDDL')
    sortEntity(action)
    print('Durative Action ' + name + ' added successfully')
    return(action)
 
 


def export_to_file():
    filename = App.ActiveDocument.Name
    file_path = App.ActiveDocument.FileName.rsplit("/", 1)[0] + filename + '_domain.pddl'

    doc = App.ActiveDocument    
    objs = doc.Objects
    with open(file_path, 'w') as f:
        f.write('(define (domain '+ filename +')\n \n')
        f.write('(:requirements :strips :typing :fluents :durative-actions)\n')
        
        # Типы обьектов
        types = doc.getObjectsByLabel('Types')[0]
        f.write('(:types \n')            
        
        for obj_type in types.Types:
            f.write('    ' + obj_type + ' \n')
        f.write(')\n')
        
        # предикаты
        f.write('   (:predicates\n')
        for obj in objs:
            if hasattr(obj, 'PDDL') and hasattr(obj, 'Type') and obj.Type == 'Predicate':
                f.write('       ('+ obj.Label)
                for params in obj.Parameters:
                    f.write(' ' + params)
                f.write(')\n')
        f.write('   )\n')
        
        # функции
        f.write('   (:functions\n')
        f.write('       )\n')
                    
        #действия:
        for obj in objs:
            if hasattr(obj, 'PDDL') and hasattr(obj, 'Type') and obj.Type == 'Action':
                f.write('(:action ' + obj.Label + '\n')
                f.write('    :parameters (')
                for params in obj.Parameters:
                    f.write('' + params + ' ')
                f.write(')\n')
                f.write('    :condition (and \n')         
                
                for condition in obj.Conditions:
                    f.write('       (' + condition + ') \n')

                f.write('  )\n')
                
                f.write('    :effect (and \n')
                
                for effect in obj.Effects:
                    f.write('       (' + effect + ') \n')
                    # f.write(' ')
                f.write(')\n')
                
                f.write('  )\n')
                
        # длительные действия:
        for obj in objs:
            if hasattr(obj, 'PDDL') and hasattr(obj, 'Type') and obj.Type == 'DurativeAction':
                f.write('(:durative-action ' + obj.Label + '\n')
                f.write('    :parameters (')
                for params in obj.Parameters:
                    f.write(' ' + params )
                f.write(' )\n')
                f.write('       :duration ( = ?duration '+ str(obj.Duration) +')\n')
                f.write('    :condition (and \n')         
                
                for condition in obj.Conditions:
                    f.write('       (' + condition + ') \n')
                    # f.write(') ')
                # f.write(')\n')
                f.write('  )\n')
                
                f.write('    :effect (and \n')
                
                for effect in obj.Effects:
                    f.write('       (' + effect + ') \n')
                    # f.write(' ')
                f.write(')\n')
                
                f.write('  )\n')
                


        f.write(' )\n')
                    


def sortEntity(object):
    doc = App.ActiveDocument

    
    if len(doc.getObjectsByLabel(object.Type)) == 0:
        pddl_group = doc.addObject("App::DocumentObjectGroup", object.Type)
    else:
        pddl_group = doc.getObjectsByLabel(object.Type)[0]
    pddl_group.addObject(object)  
      
        
    
    Gui.updateGui()
    

                
