/**
 * MapGenerator Sample Extensions
 */
package mycompany.map.modificator;

import idea.map.generator.MapGenerator;
import idea.map.matrix.AbstractMatrix;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Combination of three matrixes to one, in separate thread
 * @see UserCombinator
 * 
 * @author Lumir Vanek, vanek@idea-envi.cz
 *
 */
public class UserCombinationThread implements Runnable 
{
	/**
	 * Name of the thread
	 */
	private final String name;
		
	/**
	 * First matrix row, computed by this thread 
	 */
	private final int startRow;
	
	/**
	 * Last matrix row, computed by this thread 
	 */
	private final int endRow;
	
	/**
	 * Three Input Matrixes A, B, C and output D
	 */
	private final AbstractMatrix matrixA;
	private final AbstractMatrix matrixB;
	private final AbstractMatrix matrixC;
	private final AbstractMatrix matrixD;
	
	/**
	 * Constructor
	 * 
	 * @param name Thread name
	 * @param matrixA Input Matrix A
	 * @param matrixB Input Matrix B
	 * @param matrixC Input Matrix C
	 * @param matrixD Matrix D for output values
	 * @param startRow First matrix row, computed by this thread 
	 * @param endRow Last matrix row, computed by this thread 
	 */
	public UserCombinationThread(String name, 
			AbstractMatrix matrixA,
			AbstractMatrix matrixB,
			AbstractMatrix matrixC,
			AbstractMatrix matrixD,
			int startRow,
			int endRow)
	{
		this.name = name;
		this.matrixA = matrixA;
		this.matrixB = matrixB;
		this.matrixC = matrixC;
		this.matrixD = matrixD;
		this.startRow = startRow;
		this.endRow = endRow;
	}
	
	/**
	 * Do your work
	 */
	public void run()
	{
		try
		{
			long startTime = System.currentTimeMillis();
				
			for(int row = startRow; row <= endRow; row++)
			{	
				for(int column = 0; column < matrixA.getColumns(); column++)
				{
					combineCell(row, column);
				}
			}
			
			long endTime = System.currentTimeMillis();
			float elapsedTime = (endTime - startTime) / 1000.0f;
			
			Logger.getLogger(MapGenerator.loggerName).finer(name + 
					" of matrixes " + 
					matrixA.getId() + ", " + matrixB.getId() + ", " + matrixC.getId() + " -> " + matrixD.getId() + 
					" finished in " + elapsedTime + " sec.");
		}
		catch(Throwable t)
		{
			Logger.getLogger(MapGenerator.loggerName).log(Level.SEVERE, 
					name + " of matrixes " + 
					matrixA.getId() + ", " + matrixB.getId() + ", " + matrixC.getId() + " -> " + matrixD.getId() + " died", 
					t);
		}
	}
	
	/**
	 * Combine cells by formula D = (A > C) ? B : A
	 * 
	 * @param row Matrix row
	 * @param column Matrix column
	 */
	private void combineCell(int row, int column)
	{	
		Float a = matrixA.getValue(row, column);
		Float b = matrixB.getValue(row, column);
		Float c = matrixC.getValue(row, column);
		
		if((a == null) || (b == null) || (c == null)) return;
		
		//***************************************************
		//***************************************************
		float d = (a + b) / c ; // Only sample, use own formula
		//***************************************************
		//***************************************************
		
		matrixD.setValue(row, column, d);
	}
}