package com.elphel.imagej.orthomosaic;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class PairwiseOrthoMatch implements Serializable {
	private static final long serialVersionUID = 1L;
	public double [][]           affine = new double[2][3];
	public transient double [][] jtj =    new double [6][6];
	public int zoom_lev;
	public double rms = Double.NaN;
	public PairwiseOrthoMatch() {
		
	}
	public PairwiseOrthoMatch(
			double [][] affine,
			double [][] jtj,
			double rms,
			int zoom_lev) {
		this.affine = affine;
		this.jtj = jtj;
		this.zoom_lev=zoom_lev;
	}
	
	public PairwiseOrthoMatch getInverse(double [] rd) {
		double [][] affine = OrthoMap.invertAffine(getAffine());
		PairwiseOrthoMatch inverted_match = new PairwiseOrthoMatch(
				affine, // double [][] affine,
				null, // double [][] jtj,
				rms, // double rms,
				zoom_lev); // int zoom_lev)
		double [] corr = {
				rd[0] * (affine[0][0]-1.0)+ rd[1]*affine[0][1],
				rd[0] * affine[1][0]+       rd[1]*(affine[1][1]-1.0)};
		affine[0][2] += corr[0];
		affine[1][2] += corr[1];
		return inverted_match;	
	}

	public PairwiseOrthoMatch getInverse() {
		PairwiseOrthoMatch inverted_match = new PairwiseOrthoMatch(
				OrthoMap.invertAffine(getAffine()), // double [][] affine,
				null, // double [][] jtj,
				rms, // double rms,
				zoom_lev); // int zoom_lev)
		return inverted_match;
	}
	
	public double [][] getAffine(){
		return affine;
	}
	
	private void writeObject(ObjectOutputStream oos) throws IOException {
		oos.defaultWriteObject();
		for (int i = 0; i < jtj.length; i++) {
			for (int j = i; j < jtj[i].length; j++) {
				oos.writeObject(jtj[i][j]);
			}
		}
	}
	private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
		ois.defaultReadObject();
		jtj = new double [6][6]; // readObject does not use constructor!
		for (int i = 0; i < jtj.length; i++) {
			for (int j = i; j < jtj[i].length; j++) {
				jtj[i][j] = (Double) ois.readObject();
				if (j > i) {
					jtj[j][i] = jtj[i][j];
				}
			}
		}
	}
	//private void readObjectNoData() throws ObjectStreamException; // used to modify default values
}
