""" THIS IS A PYTHON 3 SCRIPT, BLENDER DOES NOT WORK WITH PYTHON 2.7  Generates a new file with a boolean cut"""

import bpy
import os

def Startup(bone_stl,flesh_stl):
    """Delete blender start up objects and import meshes"""
    print("Starting Blender Script")
    bpy.ops.object.select_all(action='SELECT')
    bpy.ops.object.delete()

    #import only works with stl files. Renaming needed because blender orders things alphabetically and easier to call things later
    bpy.ops.import_mesh.stl(filepath=bone_stl)
    bpy.context.selected_objects[0].name = "bone"
    bpy.ops.object.select_all(action='DESELECT')
    bpy.ops.import_mesh.stl(filepath=flesh_stl)
    bpy.context.selected_objects[0].name = "flesh"

def BooleanCut():
    """Cut the bone from the lump using boolean operations"""
    bpy.ops.object.modifier_add(type='BOOLEAN')
    bpy.context.object.modifiers["Boolean"].solver = "BMESH"
    bpy.context.object.modifiers["Boolean"].operation = 'DIFFERENCE'

    #Call the object to cut with, not the object to cut from
    bpy.context.object.modifiers["Boolean"].object = bpy.data.objects["bone"]
    bpy.ops.object.modifier_apply(apply_as='DATA', modifier="Boolean")

    #delete bone to make sure it is not exported
    bpy.ops.object.select_all(action='INVERT')
    bpy.ops.object.delete()

def Triangulate():
    """Convert Meshes Polygons back to Triangles"""
    bpy.ops.object.mode_set(mode='EDIT')
    bpy.ops.mesh.quads_convert_to_tris(quad_method='BEAUTY', ngon_method='BEAUTY')

    #Decimating less than 1% of the triangles helps remove the small/narrow triangles that can break salome without needing to completely remesh
    #Number might need to be tweaked slightly based on mesh density, increase slightly with increasing density
    bpy.ops.mesh.decimate(ratio=.995)

    #any other blender filters to apply??
def Output(flesh_file):
    output = os.path.splitext(flesh_file)[0]+"_Blender_Cut.stl"
    print("\n\n\nOUTPUT FILE LOCATED AT:\n---------------------------\n"+ output + "\n\n\n")
    bpy.ops.export_mesh.stl(filepath = output) #, check_existing = True)

def LaplaceSmooth(flesh_file):
    """Create a temporary meshlab filter to do some minimal smoothing. Probably not needed anymore but could be useful later"""
    input = os.path.splitext(flesh_file)[0] + "_Blender_Cut.stl"
    smoothed_out = os.path.splitext(flesh_file)[0] + "_Blender_Cut_LSSP.stl"
    #
    with open('temp_meshlab_filter.mlx', 'x') as f:
        f.write(
            "<!DOCTYPE FilterScript>\n<FilterScript>\n<filter name=\"Merge Close Vertices\">\n"
            + "<Param name=\"Threshold\" description=\"Merging distance\" value=\"0\" min=\"0\" max=\"1\" type=\"RichAbsPerc\"/>"
            + "\n</filter>\n <filter name=\"Laplacian smooth (surface preserve)\">\n"
            + "<Param type=\"RichBool\" value=\"false\" name=\"selection\"/>\n"
            + "<Param type=\"RichFloat\" value=\"0.5\" name=\"AngleDeg\"/>\n"
            + "<Param type=\"RichInt\" value=\"1\" name=\"iterations\"/>\n</filter>\n</FilterScript>")
    os.system("meshlabserver -i " + input + " -s temp_meshlab_filter.mlx -o " + smoothed_out)
    os.remove("temp_meshlab_filter.mlx")

    print("\n\n\nOUTPUT FILE LOCATED AT:\n---------------------------\n" + input + "\n"+ smoothed_out + "\n\n\n")



if __name__ == '__main__':
    """use full path for files. Make calls to this program with the following syntax in the terminal: 
    /path/to/blender -b -P /path/to/bpy_CutStlWithStl.py   """
    #Example:
    #/home/doherts/Documents/MULTIS/CMULTIS008_UL/meshed_femur.stl
    bone_file = "/home/doherts/Documents/MULTIS/CMULTIS008_LL/meshed_bone.stl"
    flesh_file = "/home/doherts/Documents/MULTIS/CMULTIS008_LL/5IPRSR.stl"

    #some typo checking since i got tired of closing empty blender tabs
    if(os.path.isfile(bone_file) and os.path.isfile(flesh_file)):
        Startup(bone_file,flesh_file)
        BooleanCut()
        Triangulate()
        Output(flesh_file)
        #Laplace smoothing no longer needed with the added decimation?
        LaplaceSmooth(flesh_file)

        bpy.ops.wm.quit_blender()

    elif not(os.path.isfile(bone_file)):
        print("\nERROR:\nVerify your bone file path, as the submitted path/file does not exist")

    else:
        print("\nERROR:\nVerify your flesh file path, as the submitted path/file does not exist")
