import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

import javax.swing.ButtonGroup;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/*
 * Created on 02.07.2004
 */

/**
 * 
 * @author Andreas Pleuß
 */
public class ImageFrame_Sol extends JFrame {

	private String imgPath = "long-pic2.jpg";
	private BufferedImage originalImg =  new BufferedImage(2000, 600, BufferedImage.TYPE_3BYTE_BGR);
	private BufferedImage transferredImg = new BufferedImage(500, 600, BufferedImage.TYPE_3BYTE_BGR);
	private JPanel controlPanel = new JPanel();
	private int focusX = 1000;
	private JSlider focusSlider = new JSlider(600, 1400, focusX);
	private boolean continuousFunction = false;

	public static void main(String[] args) {
		ImageFrame_Sol frame = new ImageFrame_Sol();
		frame.show();
	}
	
	public ImageFrame_Sol() {
		// init UI
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
		setSize(508, 620);
		getContentPane().add(new ImagePanel(), BorderLayout.CENTER);
		getContentPane().add(controlPanel, BorderLayout.SOUTH);
		initFocusSlider();
		initRadioButtons();
		//load image
		Image tmpImg = java.awt.Toolkit.getDefaultToolkit().createImage(imgPath);
		if (tmpImg == null) System.out.println("Error: could not load image");
		setIconImage(tmpImg);
		//trick to easily convert Image into a BufferedImage by
		//drawing the Image into the BufferedImage
		originalImg.getGraphics().drawImage(tmpImg, 0, 0, this);
		calculateTransformation();
	}
	
	private void initFocusSlider() {
		focusSlider.setMinorTickSpacing(50);
		focusSlider.setMajorTickSpacing(200);
		focusSlider.setPaintTicks(true);
		focusSlider.setPaintLabels(true);
		focusSlider.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				JSlider source = (JSlider) e.getSource();
				if (!source.getValueIsAdjusting()) {
					focusX = (int) source.getValue();
					calculateTransformation();
				}
			}

		});
		controlPanel.add(focusSlider);
	}
	
	private void initRadioButtons() {
		JRadioButton bifButton = new JRadioButton("Bifocal");
		JRadioButton contButton = new JRadioButton("Continuous");
		bifButton.setActionCommand("Bifocal");
		contButton.setActionCommand("Continuous");
		bifButton.setSelected(true);
		ActionListener buttonListener = new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(e.getActionCommand().equals("Continuous")) {
					continuousFunction = true;
					focusSlider.setEnabled(false);
				} 
				else {
					continuousFunction = false;
					focusSlider.setEnabled(true);
				} 
				calculateTransformation();
			}
		};
		bifButton.addActionListener(buttonListener);
		contButton.addActionListener(buttonListener);
		ButtonGroup bGroup = new ButtonGroup();
		bGroup.add(bifButton);
		controlPanel.add(bifButton);
		bGroup.add(contButton);
		controlPanel.add(contButton);
		
	}

	private void calculateTransformation() {
		for (int x = 0; x < originalImg.getWidth(); x++) {
			int newX;
			if(continuousFunction) newX = continuousFunction(x);
			else newX = bifocalFunction(x);
			for (int y = 0; y < originalImg.getHeight(); y++) {
				int rgbValue = originalImg.getRGB(x, y);
				try{
					transferredImg.setRGB(newX, y, rgbValue);
				}
				catch (Exception ex){
					System.out.println("Fehler: newX = " + newX);
				}
			}
		}
		repaint();
	}
	
	/* solution without slider:
	if (x < 400) y = x/8; 
	else if (x < 1600) y = 50 + (x - 400) /3;
	else y = 450 + (x - 1600) / 8;*/

	private int bifocalFunction (int x) {
		int y = 0;
		int minFoc = (focusX - 600);
		int maxFoc = (focusX + 600);
		if (x <= minFoc) y = x / 8;
		if (x > minFoc && x < maxFoc) y = minFoc/8 + (x - minFoc) / 3;
		if (x >= maxFoc) y = minFoc/8 + (maxFoc - minFoc)/3 + (x - maxFoc)/8; 
		return y;
	}
		
	private int continuousFunction (int x) {
		int y;
		int distortion = 2;
		double xRel = (1000.0 - x) / 1000.0;
		xRel = Math.abs(xRel);
		double yRel = ((distortion + 1) * xRel) / (distortion * xRel + 1);
		if (x < 1000) y = (int)Math.round(250 - 250 * yRel);
		else y = (int)Math.round(249 + 250 * yRel);		
		return y;
	}

	class ImagePanel extends JPanel {
		
		public void paint(Graphics g) {
			g.drawImage(transferredImg, 0, 0, this);
		}
	}
}

