package cz.fidentis.analyst.tests;

import cz.fidentis.analyst.BatchProcessor;
import cz.fidentis.analyst.face.HumanFace;
import cz.fidentis.analyst.face.HumanFaceFactory;
import cz.fidentis.analyst.icp.NoUndersampling;
import cz.fidentis.analyst.icp.UndersamplingStrategy;
import cz.fidentis.analyst.kdtree.KdTree;
import cz.fidentis.analyst.mesh.io.MeshObjExporter;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;

/**
 * A class for testing the efficiency of batch processing algorithms.
 * 
 * @author Radek Oslejsek
 */
public class BatchTests {
    
    private static final String DATA_DIR = "../../analyst-data/multi-scan-models-anonymized-fixed/";
    private static final String PRIMARY_FACE_PATH = DATA_DIR + "/average-boy-17-20/average_boy_17-20.obj";
    //private static final String PRIMARY_FACE_PATH = dataDir + "/average-girl-17-20/average_girl_17-20.obj";
    //private static final String PRIMARY_FACE_PATH = "../../analyst-data/basic-models/02.obj";
    //private static final String PRIMARY_FACE_PATH = dataDir + "/07/00007_01_ECA.obj";
    private static final String TEMPLATE_FACE_PATH = DATA_DIR + "template.obj";
    
    /**
     * Main method 
     * @param args Input arguments 
     * @throws IOException on IO error
     */
    public static void main(String[] args) throws IOException, ClassNotFoundException, Exception {
        BatchProcessor batch = new BatchProcessor(200); // the best is 500?
        long startTime, endTime;
        
        List<String> faceIDs;
        String primaryFaceId = HumanFaceFactory.instance().loadFace(new File(PRIMARY_FACE_PATH));
        HumanFace primaryFace = HumanFaceFactory.instance().getFace(primaryFaceId);
        KdTree primaryFacekdTree = primaryFace.computeKdTree(false);
        
        //////////////////////////////////////////////
        System.out.println();
        System.out.println("Loading files:");
        startTime = System.currentTimeMillis();
        faceIDs = batch.readFaces(DATA_DIR);
        endTime = System.currentTimeMillis();
        printTimes(startTime, endTime, faceIDs.size());
        System.out.println(faceIDs.size() + "\t\t Number of files");
        System.out.println(HumanFaceFactory.instance());
        
        //////////////////////////////////////////////
        System.out.println();
        System.out.println("Computation of symmetry planes:");
        startTime = System.currentTimeMillis();
        batch.computeSymmetryPlanes(faceIDs);
        batch.computeSymmetryPlanes(Collections.singletonList(primaryFaceId));
        endTime = System.currentTimeMillis();
        printTimes(startTime, endTime, faceIDs.size());
        
        //////////////////////////////////////////////
        UndersamplingStrategy strategy = new NoUndersampling();
        //UndersamplingStrategy strategy = new RandomStrategy(0.5);
        System.out.println();
        System.out.println("ICP registration with " + strategy + ":");
        startTime = System.currentTimeMillis();
        batch.superimposeOnPrimaryFace(primaryFaceId, faceIDs, 10, 0.05, strategy);
        endTime = System.currentTimeMillis();
        printTimes(startTime, endTime, faceIDs.size());
        System.out.printf("%.2f \t\t Avg number of iterations", batch.getAvgNumIcpIterations());
        System.out.println();
        
        //////////////////////////////////////////////
        System.out.println();
        System.out.println("Computation of averaged template face:");
        startTime = System.currentTimeMillis();
        batch.computeTemplateFace(primaryFaceId, faceIDs);
        endTime = System.currentTimeMillis();
        printTimes(startTime, endTime, faceIDs.size());
        System.out.println("Writing average template to " + TEMPLATE_FACE_PATH);
        MeshObjExporter exp = new MeshObjExporter(batch.getAvgTemplateFace().getMeshModel());
        exp.exportModelToObj(new File(TEMPLATE_FACE_PATH));
    }
    
    private static void printTimes(long startTime, long endTime, int numFaces) {
        double timeDist = endTime - startTime;
        double avgTime = (timeDist/numFaces)/1000.0;
        System.out.printf("%.2f sec \t Overall time", timeDist/1000.0);
        System.out.println();
        System.out.printf("%.2f sec \t Average time", avgTime);
        System.out.println();
        System.out.printf("%.2f min \t Estimated time for 500 faces", (avgTime*500)/60);
        System.out.println();
    }
}
