package com.gradesscope.photoeditor;

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

/**
 * Class to display an image and the current location with a + sign.
 * 
 * @author Barb Ericson (ericson@cc.gatech.edu)
 * 	(Copyright Georgia Institute of Technology 2004)
 */
public class ImageDisplay extends JPanel implements Scrollable
{

	/////////////////////////// Fields (attributes) ///////////////////////////
	
	private Image image;         // the image to draw
	private Dimension prefSize;  // the preferred size of the display
	private int currentX = 0;    // the current x index 
	private int currentY = 0;    // the current y index
	private static final long serialVersionUID = 0; 
	
	//////////////////////////// Constructors /////////////////////////////////

	/**
	 * A constructor that takes the Image to display.
	 * 
	 * @param theImage The Image to display.
	 */
	public ImageDisplay(Image theImage) {
		this.image = theImage;
		this.prefSize = new Dimension(this.image.getWidth(this), this.image.getHeight(this));
		this.setPreferredSize(prefSize);
		this.revalidate();
	}

	/**
	 * Constructor that takes an Image and current x- and y-values.
	 * 
	 * @param theImage The Image to display.
	 * @param x The current x-value.
	 * @param y The current y-value.
	 */
	public ImageDisplay(Image theImage, int x, int y) {
		this(theImage);
		this.currentX = x;
		this.currentY = y;
	}

	///////////////////////////////// Methods /////////////////////////////////

	/**
	 * @return The associated Image.
	 */
	public Image getImage() { return this.image; }

	/**
	 * @return The current x-value.
	 */
	public int getCurrentX() { return this.currentX; }

	/**
	 * @return the current y-value.
	 */
	public int getCurrentY() { return this.currentY; }

	/**
	 * Sets the current x-value.
	 * 
	 * @param x The x-value to use.
	 */
	public void setCurrentX(int x) {
		this.currentX = x;
		this.repaint();
	}

	/**
	 * Sets the current y-value.
	 * 
	 * @param y The y-value to use.
	 */
	public void setCurrentY(int y) {
		this.currentY = y;
		this.repaint();
	}

	/**
	 * Sets the associated Image.
	 * 
	 * @param theImage The new Image to use.
	 */
	public void setImage(Image theImage) {
		this.image = theImage;
		this.setPreferredSize(new Dimension(this.image.getWidth(this),
				this.image.getHeight(this)));
		this.repaint();
	}

	/**
	 * @return The preferred size of this component.
	 */
	public Dimension getPreferredScrollableViewportSize() {
		return this.prefSize;
	}

	/**
	 * @param visibleRect The visible rectangle.
	 * @param orientation Whether orientation is vertical or horizontal.
	 * @param direction Negative value is up or left and
	 * 	positive value is right or down.
	 * 
	 * @return The unit increment for clicking in scroll area.
	 */
	public int getScrollableUnitIncrement(Rectangle visibleRect, 
			int orientation, int direction) { return 1; }

	/**
	 * Returns the block increment for scrolling.
	 * 
	 * @param visibleRect The visible rectangle.
	 * @param orientation Whether orientation is vertical or horizontal.
	 * @param direction Negative value is up or left and
	 * 	positive value is right or down.
	 * 
	 * @return The block increment for clicking in scroll area.
	 */
	public int getScrollableBlockIncrement(Rectangle visibleRect, 
			int orientation, int direction) { return 10; }

	/**
	 * @return True if viewport and source have same width
	 */
	public boolean getScrollableTracksViewportWidth() { return false; }

	/**
	 * @return True if viewport and source have same height
	 */
	public boolean getScrollableTracksViewportHeight() { return false; }

	/**
	 * Handles displaying this object.
	 * 
	 * @param g The graphics object to draw with.
	 */
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		int num = 3;
		int xStart = currentX - num;
		int xEnd = currentX + num;
		int yStart = currentY - num;
		int yEnd = currentY + num;
		int width = this.image.getWidth(this);
		int maxX = width - 1;
		int height = this.image.getHeight(this);
		int maxY = height - 1;

		// Draw the image
		g.drawImage(image, 0, 0, this);

		// Check if the current index is in the image.
		if (currentX >= 0 && currentX < width &&
				currentY >= 0 && currentY < height)
		{
			// Check that the start and end values are visible.
			if (xStart < 0){
				xStart = 0;
			}
			if (xEnd > maxX){
				xEnd = maxX;
			}
			if (yStart < 0){
				yStart = 0;
			}
			if (yEnd > maxY){
				yEnd = maxY;
			}

			/* Draw a small cross at the current x- and y-
			 * coordinates in yellow.
			 */
			g.setColor(Color.yellow);
			g.drawLine(xStart,currentY,xEnd,currentY);
			g.drawLine(currentX,yStart,currentX,yEnd);
			g.setColor(Color.black);

			// Outline the cross in black so that it shows up better.
			int leftX = currentX - 1;
			int rightX = currentX + 1;
			int upY = currentY - 1;
			int downY = currentY + 1; 
			if (xStart <= leftX && upY >= 0){
				g.drawLine(xStart, upY, leftX, upY);
			}
			if (yStart <= upY && leftX >= 0){
				g.drawLine(leftX, yStart, leftX, upY);
			}
			if (yStart <= upY && rightX <= maxX){
				g.drawLine(rightX, yStart, rightX, upY);
			}
			if (upY >= 0 && rightX <= xEnd){
				g.drawLine(rightX, upY, xEnd, upY);
			}
			if (downY < height && rightX <= xEnd){
				g.drawLine(rightX, downY, xEnd, downY);
			}
			if (downY <= yEnd && rightX < width){
				g.drawLine(rightX, downY, rightX, yEnd);
			}
			if (xStart <= leftX && downY < height){
				g.drawLine(xStart, downY, leftX, downY);
			}
			if (leftX >= 0 && downY <= yEnd){
				g.drawLine(leftX, downY, leftX, yEnd);
			}
		}
	}

} // End of ImageDisplay class.
