#!/usr/bin/env python
# 2022-04: Python2 to Python3 conversion by Allison Hsiang
# 2022-07: Change from external ImageJ/FIJI installation to pyimagej API by Allison Hsiang

import initialize
import settings
import checkpoint
import heightmap
import mesh
import volume
import objoff
import pdf

import argparse
import inspect
import shutil
import os
import glob
import socket


version = '2022-07'

def morph3d(control_file,reset):
    # Print run3dmorph version and time stamp
    initialize.displayVersion(version)
    initialize.displayTime()

    # Load settings from control file
    print ('INFO: Loading settings from %s...\n' % control_file)
    run = settings.parse(control_file)
    settings.save(run)

    morph3dPath = os.path.join(run['out_directory'], 'morph3d')

    # Reset if requested and previous run output exists
    if reset:
        if os.path.exists(morph3dPath):
            print ('INFO: Resetting previous run3dmorph run...\n')
            initialize.resetRun(morph3dPath)
        else:
            print ('INFO: Reset requested, but no previous run3dmorph output found. Continuing...\n')

    # Create output folders and initialize objects to process
    initialize.makeOutputFolders(run, morph3dPath)
    allObjects = initialize.initializeObjects(run)

    # Checkpointing
    cpFile = os.path.join(morph3dPath,'checkpoint.txt')
    restart,lastObj = checkpoint.checkRestart(cpFile, allObjects)
    if restart:
        print ('INFO: Checkpoint file found; Restarting from save point...\n')
        objects = checkpoint.setRestartObjects(lastObj, allObjects)
    else:
        objects = allObjects

    # Get path of third-party libraries
    libPath = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'lib'))

    # Start ImageJ instance
    if not run['docker']: # Pyimagej
        ij, temp_plugins_dir = heightmap.initImageJ(libPath)
    else: # Docker
        ij = None

    for obj in objects:
        # Print name of current object
        obj.showObject()

        # Generate height map
        print ('\tINFO: Generating height map...')
        heightmap.makeHeightMap(run, obj, ij)

        # Extract mesh
        print ('\tINFO: Beginning mesh extraction...')
        edge, image_clean, triangulation, triangles, faceColors, length, width, bottom_height, top_height = mesh.extractMesh(run,obj)

        # Get total volume and surface area estimates
        print ('\tINFO: Estimating object surface area and volume...')
        volume.getVolumeSurfaceArea(run, obj, image_clean, edge, triangulation, triangles, length, width, bottom_height, top_height)

        # Save mesh in OBJ and OFF format
        print ('\tINFO: Saving OBJ and OFF files...')
        objoff.saveOBJOFF(run, obj, triangulation)

        # Build 3D PDF
        if run['latex']:
            print ('\tINFO: Generating 3D PDF...')
            pdf.makePDF(run, obj, libPath, triangulation, triangles, faceColors, length, width)
        else:
            print ('\tINFO: 3D PDF generation not requested.\n')

        # Checkpointing
        checkpoint.saveCheckpoint(obj, cpFile)

    # Cleanup
    if not run['docker']:
        shutil.rmtree(temp_plugins_dir)

    print ('INFO: Run3dmorph process completed.\n')


if __name__ == "__main__":
    # If we're running this on the Tide machine at Yale, be nice to other users
    if socket.gethostname() == 'tide.geology.yale.edu':
        os.nice(10)

    # Set up parser to deal with command line arguments
    parser = argparse.ArgumentParser(description='')
    parser.add_argument('control_file',
                        help='path to control file')
    parser.add_argument('--reset',
                        help='removes existing morph3d directory in output directory',
                        action='store_true')
    args = parser.parse_args()

    # Set control file
    control_file = os.path.realpath(args.control_file)

    # Start run
    if args.reset:
        morph3d(control_file,args.reset)
    else:
        morph3d(control_file,False)
