package com.elphel.imagej.tileprocessor;

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicInteger;

import com.elphel.imagej.cameras.CLTParameters;
import com.elphel.imagej.ims.Did_ins_2;
import com.elphel.imagej.ims.Imx5;

public class SeriesInfinityCorrection {

	public static double getInfinityMuliSeries(
    		CLTParameters    clt_parameters,
    		QuadCLT []       refCLTs,
    		QuadCLT          index_CLT, // normally - just the last in quadCLTs
    		final int        debugLevel) {
		for (QuadCLT ref_scene:refCLTs) {
			ref_scene.restoreAnyDSI(debugLevel);
		}
		// get all scenes used in at least one segment.
		HashSet<String> scene_set = new HashSet<String>();
		for (QuadCLT ref_scene:refCLTs) {
			ErsCorrection ers_reference = ref_scene.getErsCorrection();
			String [] names = ers_reference.getScenes();
			for (String s:names)scene_set.add(s);
		}
		String [] all_scene_names = scene_set.toArray(new String[0]);
		Arrays.sort(all_scene_names);
		HashMap<String,QuadCLT> scene_map = new HashMap<String,QuadCLT>(); 
		String models_dir = index_CLT.correctionsParameters.x3dDirectory;
		final String suffix = index_CLT.correctionsParameters.imsSuffix; // assuming common for all
		final QuadCLT[] scenes = new QuadCLT[all_scene_names.length];
		
		final Thread[] threads = ImageDtt.newThreadArray();
		final AtomicInteger ai = new AtomicInteger(0);
		for (int ithread = 0; ithread < threads.length; ithread++) {
			threads[ithread] = new Thread() {
				public void run() {
					for (int iScene = ai.getAndIncrement(); iScene < scenes.length; iScene = ai.getAndIncrement()) {
						QuadCLT scene = new QuadCLT(index_CLT, all_scene_names[iScene]);
						Path ims_path = Paths.get(models_dir).resolve(all_scene_names[iScene]).resolve(all_scene_names[iScene]+suffix);
						scene.restoreIms(
						            clt_parameters, // // CLTParameters clt_parameters,
						            ims_path.toString(), // String ims_path,
						            true, // boolean create,
						            debugLevel-1); // debugLevelInner); // int debugLevel);
						scenes[iScene] = scene;
					}
				}
			};
		}		      
		ImageDtt.startAndJoin(threads);
		for (int nscene = 0; nscene < all_scene_names.length; nscene++) { // scene_name:all_scene_names) {
			scene_map.put(all_scene_names[nscene], scenes[nscene]);
		}
		// Now iterate through the reference scenes, using IMS data from the scene_map scenes.
		// initially will use earliest and latest scenes only. Improve for the future non-linear flying multicopters
		// and account for sync loss (far samples with random coordinates)
		double [] img_scales =  new double[refCLTs.length];
		double [] dist_visual = new double[refCLTs.length];
		double [] dist_ims2 =   new double[refCLTs.length];
		for (int nref = 0; nref < refCLTs.length; nref++) {
			QuadCLT ref_scene = refCLTs[nref];
			ErsCorrection ers_reference = ref_scene.getErsCorrection();
			// This does not work, as there can be stale in ers_reference.getScenes();
			
//			String [] sts = ers_reference.getScenes();
//			String [] first_last_ts = {sts[0],sts[sts.length - 1]};
			String [] first_last_ts = ref_scene.getFirstLastTimestamps();
			
			double[][] xyz_fl = new double [first_last_ts.length][];
			Did_ins_2 [] did_2_fl= new Did_ins_2 [first_last_ts.length];
			for (int n = 0; n < first_last_ts.length; n++) {
				String ts= first_last_ts[n];
				xyz_fl[n] = ers_reference.getSceneXYZ(ts);
				did_2_fl[n] = scene_map.get(ts).did_ins_2;
			}
			double travel_visual2 = 0;
			double travel_ims2 = 0;
			double [] dned = Imx5.nedFromLla (did_2_fl[1].lla, did_2_fl[0].lla);
			for (int i = 0; i < 3; i++) {
				double dv = xyz_fl[1][i]-xyz_fl[0][i];
				travel_visual2 += dv*dv;
				travel_ims2 += dned[i]*dned[i];
			}
			dist_visual[nref] = Math.sqrt(travel_visual2);
			dist_ims2[nref] =   Math.sqrt(travel_ims2);
			img_scales[nref] =  Math.sqrt(travel_visual2/travel_ims2);
		}
		double sw = 0.0, swd = 0.0, sw_vis=0, sw_ims=0;
		for (int nref = 0; nref < refCLTs.length; nref++) {
			double w = 1.0;
			sw += w;
			swd += w * img_scales[nref];
			sw_vis += dist_visual[nref];
			sw_ims += dist_ims2[nref];
		}
		double img_scale = swd/sw;
		if (debugLevel > -3) {
			System.out.println("ts\timg_scale\tdist_visual\tdist_ims");
			for (int nref = 0; nref < refCLTs.length; nref++) {
				System.out.println(refCLTs[nref].getImageName()+"\t"+img_scales[nref]+"\t"+dist_visual[nref]+"\t"+dist_ims2[nref]);
			}			
			System.out.println("Average\t"+img_scale+"\t"+(sw_vis/sw)+"\t"+(sw_ims/sw));
		}
    	return img_scale;
    }
	
	/*
		SetChannels [] set_channels=quadCLT_main.setChannels(debugLevel);
		QuadCLT [] quadCLTs = new QuadCLT [set_channels.length]; 
		for (int i = 0; i < quadCLTs.length; i++) {
			quadCLTs[i] = (QuadCLT) quadCLT_main.spawnQuadCLT(
					set_channels[i].set_name,
					clt_parameters,
					colorProcParameters, //
					threadsMax,
					debugLevel);
			quadCLTs[i].setDSRBG(
					clt_parameters, // CLTParameters  clt_parameters,
					threadsMax,     // int            threadsMax,  // maximal number of threads to launch
					updateStatus,   // boolean        updateStatus,
					debugLevel);    // int            debugLevel)
		}
		if (ref_index < 0) {
			ref_index += quadCLTs.length;
		}
			
	 * 
	 * 
   public static double getImgImsScale( // correctInfinityFromIMS(
			QuadCLT []       quadCLTs,
			QuadCLT          master_CLT,
			int              earliest_scene,
			int              latest_scene) { // -1 will use quadCLTs.length -1;

	 */
	
}
