/*******************************************************************************
 * Copyright (c) 2010 Attila Kovacs <attila_kovacs@post.harvard.edu>.
 * All rights reserved. 
 * 
 * This file is part of crush.
 * 
 *     crush is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     crush is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License
 *     along with crush.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Contributors:
 *     Attila Kovacs <attila_kovacs@post.harvard.edu> - initial API and implementation
 ******************************************************************************/
// Copyright (c) 2007 Attila Kovacs 

package crush.gui;

import util.*;
import crush.gui.colorscheme.*;

import java.awt.*;
import javax.swing.*;

public class ColorMapPanel extends JPanel {
	/**
	 * 
	 */
	private static final long serialVersionUID = 8063198567194226851L;

	float[][] data;
		
	ColorScheme colorScheme;
	Scale scale;
	boolean inverted = false;

	// Rendering parameters
	int spacing = 0;

	public ColorMapPanel() {
		setDefaults();
	}

	public ColorMapPanel(float[][] map) {
		setData(map);
		setDefaults();
	}

	public void setData(float[][] data) {
		this.data = data;
	}
	
	public void setDefaults() {
		colorScheme = new CameraLike();
		// TODO set the scale to the full range of the data...
	}
	
	Graphics paintedArea;
	Rectangle clip;
	
	@Override
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		
		getClipRectangle();
		
		dx = (float) clip.getWidth() / data.length;
		dy = (float) clip.getHeight() / data[0].length;
		
		dw = Math.max(1, (int)Math.ceil(dx) - spacing); // Always draw at least one pixel per point...
		dh = Math.max(1, (int)Math.ceil(dy) - spacing); // Or with the desired border width...
		
		paintedArea = g.create(clip.x, clip.y, clip.width, clip.height);
		
		final int nx = data.length;
		final int ny = data[0].length;
		
		for(int j=nx; --j >= 0; ) for(int i=ny; --i >= 0; ) drawPoint(i, j); 
	}
	
	// By default the image will fill the the full panel...
	public void getClipRectangle() {
		clip = new Rectangle(0, 0, getWidth(), getHeight());
	}
	
	private float dx, dy;
	private int dw, dh;
	
	private final void drawPoint(final int i, final int j) {	
		double value = data[i][j];
	
		if(Double.isNaN(value)) return; // skip NaN values.
		
		float scaled = (float) scale.getScaled(value);
		if(Double.isNaN(scaled)) scaled = 0.0F; // needed for log scaling...
		if(inverted) scaled = 1.0F - scaled;

		paintedArea.setColor(colorScheme.getColor(scaled));
		paintedArea.fillRect((int) Math.floor(i*dx), (int) Math.floor(clip.height-(j+1)*dy), dw, dh);
	}
	
	
	public void setSpacing(int thickness) {
		spacing = thickness;
	}
	
	public double geti(int x) {
		return (x - clip.x) / dw;
	}
	
	
	public double getj(int y) {
		return (clip.height - (y - clip.y)) / dy;
	}
	
	public int getInti(int x) {
		return (int) Math.round(geti(x));
	}
	
	public int getIntj(int y) {
		return (int) Math.round(getj(y));
	}
	
	
	
}



