package client.skin;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
import client.backend.BatchAdapter;
import client.backend.ClientBackEnd;

public class ReadingPanel extends JComponent
{
	private static final long serialVersionUID = -237588719990648006L;
	
	private ClientBackEnd backEnd;
	
	public ReadingPanel(ClientBackEnd backEnd)
	{
		this.backEnd = backEnd;
		backEnd.addBatchListener(imageListener);
		this.addMouseListener(mouseListener);
		this.addMouseMotionListener(mouseListener);
		this.addMouseWheelListener(mouseListener);
		
		this.setBackground(Color.DARK_GRAY);
	}
	
	@Override
	protected void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D)g;
		
		// Background.
		g2.setColor(this.getBackground());
		g2.fillRect(0,  0, getWidth(), getHeight());
		
		// Image.
		BufferedImage img = backEnd.getImg();
		if(img != null)
		{
			// Transform.
			g2.translate(this.getWidth()/2, this.getHeight()/2);
			g2.scale(backEnd.getScale(), backEnd.getScale());
			g2.translate(this.getWidth()/2 + backEnd.getImgDeviceX(), -this.getHeight()/2 + backEnd.getImgDeviceY());
			
			// Image proper.
			if(backEnd.isInverted())
			{
				img = invert(img);
			}

			g2.drawImage(img, 0, 0, null);
			
			// Highlight.
			if(backEnd.isHighlighted())
			{
				int xStart = backEnd.getFields().get(backEnd.getSelectedCol()).getXCoord();
				int xWidth = backEnd.getFields().get(backEnd.getSelectedCol()).getWidth();
				int yStart = backEnd.getFirstYCoord() + backEnd.getRecordHeight() * backEnd.getSelectedRow();
				int yHeight = backEnd.getRecordHeight();
				
				g2.setColor(new Color(50, 50, 255, 100));
				g2.fillRect(xStart, yStart, xWidth, yHeight);
			}
		}
	}
	
	private BufferedImage invert(BufferedImage orig)
	{
		BufferedImage output = new BufferedImage(orig.getWidth(), orig.getHeight(), BufferedImage.TYPE_INT_ARGB);
		
		for(int i = 0; i < orig.getWidth(); i++)
		{
			for(int j = 0; j < orig.getHeight(); j++)
			{
				// For each pixel,
				Color pixel = new Color(orig.getRGB(i, j), true);
				pixel = new Color(255 - pixel.getRed(), 255 - pixel.getGreen(), 255 - pixel.getBlue()); // Invert.
				output.setRGB(i, j, pixel.getRGB());
			}
		}
		
		return output;
	}
	
	private MouseAdapter mouseListener = new MouseAdapter()
	{
		int mouseStartX = 0, mouseStartY = 0, mouseStartOriginX = 0, mouseStartOriginY = 0;
		
		@Override
		public void mousePressed(MouseEvent e)
		{
			mouseStartX = e.getX();
			mouseStartY = e.getY();
			mouseStartOriginX = backEnd.getImgDeviceX();
			mouseStartOriginY = backEnd.getImgDeviceY();
		}

		@Override
		public void mouseDragged(MouseEvent e)
		{		
			int mouseXDist = e.getX() - mouseStartX;
			int mouseYDist = e.getY() - mouseStartY;
			
			backEnd.setImgDeviceX(mouseStartOriginX + mouseXDist);
			backEnd.setImgDeviceY(mouseStartOriginY + mouseYDist);
			
			repaint();
		}

		@Override
		public void mouseReleased(MouseEvent e)
		{
			mouseStartX = 0;
			mouseStartY = 0;
			mouseStartOriginX = 0;
			mouseStartOriginY = 0;
		}

		@Override
		public void mouseWheelMoved(MouseWheelEvent e)
		{
			boolean zoomingOut = e.getWheelRotation() > 0;
			int zoomUnits = Math.abs(e.getWheelRotation());
			
			for(int i = 0; i < zoomUnits; i++)
			{
				if(zoomingOut)
				{
					backEnd.zoomOut();
				}
				else
				{
					backEnd.zoomIn();
				}
			}
		}	
	};
	
	private BatchAdapter imageListener = new BatchAdapter()
	{
		@Override
		public void imageUpdated(ActionEvent e)
		{
			repaint();
		}

		@Override
		public void imageZoomUpdated(ActionEvent e)
		{
			repaint();
		}
		
		@Override
		public void imagePositionUpdated(ActionEvent e)
		{
			repaint();
		}
		
		@Override
		public void imageHighlightsUpdated(ActionEvent e)
		{
			repaint();
		}
		
		@Override
		public void imageInverted(ActionEvent e)
		{
			repaint();
		}

		@Override
		public void tableGridUpdated(ActionEvent e)
		{
			repaint();
		}
		
		@Override
		public void cellSelectionChanged(ActionEvent e)
		{
			repaint();
		}
	};
}
