import sys, os

# Add the igl library to the modules search path
sys.path.insert(0, os.getcwd() + "/../")
import pyigl as igl

from shared import TUTORIAL_SHARED_PATH, check_dependencies

dependencies = ["cgal", "viewer"]
check_dependencies(dependencies)

boolean_type_names = {igl.MESH_BOOLEAN_TYPE_UNION: "Union", igl.MESH_BOOLEAN_TYPE_INTERSECT: "Intersect", igl.MESH_BOOLEAN_TYPE_MINUS: "Minus", igl.MESH_BOOLEAN_TYPE_XOR: "XOR", igl.MESH_BOOLEAN_TYPE_RESOLVE: "Resolve"}

boolean_types = list(boolean_type_names.keys())




def update(viewer):
    print("Calculating A %s B..." % boolean_type_names[boolean_type])
    igl.cgal.mesh_boolean(VA, FA, VB, FB, boolean_type, VC, FC, J)
    C = igl.eigen.MatrixXd(FC.rows(), 3)

    for f in range(C.rows()):
        if J[f] < FA.rows():
            C.setRow(f, Red)
        else:
            C.setRow(f, Green)

    viewer.data.clear()
    viewer.data.set_mesh(VC, FC)
    viewer.data.set_colors(C)
    print("Done.")


def key_down(viewer, key, modifier):
    global boolean_type

    if key == ord('.'):
        boolean_type = boolean_types[(boolean_types.index(boolean_type) + 1) % (len(boolean_types))]
    elif key == ord(','):
        boolean_type = boolean_types[(boolean_types.index(boolean_type) + len(boolean_types) - 1) % len(boolean_types)]
    elif key == ord('['):
        viewer.core.camera_dnear -= 0.1
    elif key == ord(']'):
        viewer.core.camera_dnear += 0.1
    else:
        return False

    update(viewer)

    return False


if __name__ == "__main__":

    VA = igl.eigen.MatrixXd()
    FA = igl.eigen.MatrixXi()
    VB = igl.eigen.MatrixXd()
    FB = igl.eigen.MatrixXi()
    VC = igl.eigen.MatrixXd()
    FC = igl.eigen.MatrixXi()
    J = igl.eigen.MatrixXi()

    Red = igl.eigen.MatrixXd([[1, 0, 0]])
    Green = igl.eigen.MatrixXd([[0, 1, 0]])

    # Load meshes in OFF format
    igl.readOFF(TUTORIAL_SHARED_PATH + "cheburashka.off", VA, FA)
    igl.readOFF(TUTORIAL_SHARED_PATH + "decimated-knight.off", VB, FB)

    boolean_type = igl.MESH_BOOLEAN_TYPE_UNION

    viewer = igl.viewer.Viewer()
    update(viewer)

    print(
        "Usage: Press '.' to switch to next boolean operation type. \nPress ',' to switch to previous boolean operation type. \nPress ']' to push near cutting plane away from camera. \nPress '[' to pull near cutting plane closer to camera. \nHint: investigate _inside_ the model to see orientation changes. \n")

    viewer.core.show_lines = True
    viewer.callback_key_down = key_down
    viewer.core.camera_dnear = 3.9
    viewer.launch()