/*************************************************
 * Author: 	Evelyn Lai-Tee Cheok
 *			Department of Electrical Engineering
 *			Center for Telecommunications Research
 *			Schapiro Research Building
 *			Columbia University
 *
 * Email: 	laitee@ctr.columbia.edu
 *
 **************************************************/
import java.lang.*;
import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.*;
import SketchArea;
import ObjType;
import SenderMCSocket;
import PacketHandler;


public class Img extends ObjBaseClass implements DrawObject, Cloneable {

	SketchArea parent;
	Image image;
	public int x1, y1, old_x1, old_y1;
	public int dist_x, dist_y;
	public int imageWidth, imageHeight;
	String imageURL = null;
	public int type;
	public int obj_id = 0;
	public int color = 0;
	Random rand_gen = new Random(System.currentTimeMillis());
	Toolkit wbToolkit = Toolkit.getDefaultToolkit();

	/**
	 * constructor
	 *
	 *@param parent SketchArea object reference
	 *@param c color type
	 *@return none
	 *@exception none
	 */

	public Img(SketchArea parent) {
		super(parent.parent.senderSock, parent.parent.pkt_handler);
		this.parent = parent;
		type = ObjType.IMAGE;
		obj_id = (int) (rand_gen.nextFloat() * 2000);
	}

	/**
	 * constructor
	 *
	 *@param parent SketchArea reference
	 *@return none
	 *@exception none
	 */

	public Img(SketchArea parent, Image img, 
				int x, int y, URL gifURL) {
		super(parent.parent.senderSock, parent.parent.pkt_handler);
		this.parent = parent;
		image = img;
		x1 = x;
		y1 = y;
		imageWidth = img.getWidth(null);
		imageHeight = img.getHeight(null);
		imageURL = gifURL.toString();
		System.out.println("Image URL in String = |"+imageURL+"|");
		type = ObjType.IMAGE;

		System.out.println(" **** In Img class");
		System.out.println(" imageWidth = "+imageWidth);
		System.out.println(" imageHeight = "+imageHeight);
	}

	public Img(SketchArea parent, Image img, 
				int x, int y, int width, int height,
				URL gifURL) {
		super(parent.parent.senderSock, parent.parent.pkt_handler);
		this.parent = parent;
		image = img;
		x1 = x;
		y1 = y;
		imageWidth = width;
		imageHeight = height;
		imageURL = gifURL.toString();
		System.out.println("Image URL in String = |"+imageURL+"|");
		type = ObjType.IMAGE;

		System.out.println(" **** In Img class");
		System.out.println(" imageWidth = "+imageWidth);
		System.out.println(" imageHeight = "+imageHeight);
	}
	/** clones a line object by making an exact copy of this line object
	  * with values equal to the original values, except that the starting
	  * and ending points of the newly cloned line are translated by a value of
	  * TRANSLATE_X and TRANSLATE_Y defined in the ObjBaseClass.java.
	  * @return a cloned object.
	  **/
	public Object clone() {
		try {
			Img cloneimage = (Img)super.clone();
			cloneimage.x1 += TRANSLATE_X;
			cloneimage.y1 += TRANSLATE_Y;
			cloneimage.obj_id = (int)(rand_gen.nextFloat() * 2000);
			return cloneimage;
		} catch (CloneNotSupportedException e) {
			System.out.println("CLoneNotSupportedException : "+e);
			throw new InternalError(e.toString());
		}
	}

	public void setBaseDist(Graphics g, int x, int y) {
		dist_x = x - x1;
		dist_y = y - y1;
		erase(g, false);
	}

	/**
	 * event handler for mouse down while drawing
	 *
	 *@param x x value
	 *@param y y value
	 *@return true
	 *@exception none
	 */

	public boolean mouseDown(int x, int y) {

		return true;
	}

	/**
	 * event handler for mouse up when drawing objects
	 *
	 *@param x x value
	 *@param y y value
	 *@return true
	 *@exception none
	 */

	public boolean mouseUp(int x, int y) {

		return true;
	}

	public void send() {
		if ( (imageWidth != -1) && (imageHeight != -1) ) {
			System.out.println("image width and height != -1");
			assemble(ObjType.IMAGE);
		}
	}

	/**
	 * event handler for mouse drag when drawing the objects
	 *
	 *@param x x value
	 *@param y y value
	 *@return true
	 *@exception none
	 */

	public boolean mouseDrag(int x, int y) {

		return true;
	}

	/**
	 * function called when moving the object
	 *
	 *@param x x value
	 *@param y y value
	 *@return void
	 *@exception none
	 */


	public void moving(Graphics g, int x, int y) {
		old_x1 = x1;
		old_y1 = y1;

		setBasePoint(x, y);
		clear(g);
		assemble(ObjType.MOVE);
	}

	public void setBasePoint(int x, int y) {
		x1 = x - dist_x;
		y1 = y - dist_y;
	}

	public void recvd_moved_obj(Graphics g, int recvd_x1, int recvd_y1,
				     int recvd_x2, int recvd_y2) {
		/*old_x = x2;
		old_y = y2;
		clean(g);
		x1 = recvd_x1;
		y1 = recvd_y1;
		x2 = recvd_x2;
		y2 = recvd_y2;
		paint(g);
		*/
	}

	/**
	 * set parameter after locating the last point
	 *
	 *@param g graphics context
	 *@param x x value
	 *@return y y value
	 *@exception none
	 */

	public void moveUP(Graphics g, int x, int y) {
		setBasePoint(x, y);
		clear(g);
	}

	/**
	 * draw object which is passed from network
	 *
	 *@return void
	 */

	public void draw() {
		 try {
		 	image = wbToolkit.getImage(new URL(imageURL));
		 } catch (MalformedURLException e) {
		 	System.out.println("MalformedURLException in draw() : "+e);
		 }

		 if ( image != null ) {
			System.out.println("x1 = "+x1+"  y1 = "+y1+"  imageWidth = "+imageWidth+
								"  imageHeight = "+imageHeight);
		 	paint(parent.offscreenG);
		 	parent.repaint();
		 	parent.addStack((Object) this);
		 	System.out.println("Image received is NOT NULL");

		 }
		 else
		 	System.out.println("Image received is NULL");
	}


	/**
	 * draw the object by pen color
	 *
	 *@param g graphics context
	 *@return void
	 *@exception none
	 */

	public void paint(Graphics g) {
		g.drawImage(image, x1, y1, imageWidth, imageHeight, null);
		//g.drawImage(image, x1, y1, null);
	}

	/**
	 * clear up object on the whiteboard
	 *
	 *@param g Graphics context
	 *@return void
	 *@exception none
	 */

	public void clear(Graphics g) {
		clean(g);
		paint(g);
	}

	public void clean(Graphics g) {
		g.setColor(parent.getBackground());
		g.fillRect(old_x1, old_y1, old_x1+imageWidth, old_y1+imageHeight);
	}

	public void erase(Graphics g, boolean send_del_req) {
		g.setColor(parent.getBackground());
		g.fillRect(x1, y1, x1+imageWidth, y1+imageHeight);
		if (send_del_req == true)
			assemble(ObjType.DELETE);
	}


	/**
	 * assembles the Line object's parameters based on application-specific
	 * format before calling superclass's BaseClassAssemble for assembling
	 * this resulting packet with the RTP header. This function is called
	 * by mouseUp Event.
	 *
	 *@author Lai-Tee Cheok
	 *
	 *@return void
	 *@exception none
	 */

	public void assemble(int ObjectType) {
		ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
		DataOutputStream dataStream = new DataOutputStream(byteStream);
		 byte[] data_buf = new byte[1024];

		 try {
			dataStream.writeByte(DataType.WBDataType);
			dataStream.writeByte(ObjectType);
			dataStream.writeInt(obj_id);
			if (ObjectType != ObjType.DELETE) {
				dataStream.writeByte((byte)color);

				if (ObjectType == ObjType.IMAGE) {
					dataStream.writeByte(imageURL.length());
					dataStream.writeBytes(imageURL);
				}

				dataStream.writeShort(x1);
				dataStream.writeShort(y1);
				// Probably should writeInt instead of writeShort since
				// we could be dealing with big images that can't be handled
				// by Short variable type.
				System.out.println("$$$ sending image parameters : ");
				System.out.println("imageWidth = "+ imageWidth + "  imageHeight = "+
									imageHeight);
				dataStream.writeShort(imageWidth);
				dataStream.writeShort(imageHeight);
			}
		} catch(java.io.IOException e) {
			System.out.println("IOException in Line Object assembling: " + e);
		}

		data_buf = byteStream.toByteArray();
		BaseClassAssemble(data_buf);
	}

	/**
	 * retrieves Line object's parameters from the received packet and
	 * display the line on the drawing canvas of the whiteboard.
	 *
	 * @author: Lai-Tee Cheok
	 *
	 *@param buf buffer that holds parameters in the form of byte array.
	 *@return void
	 *@exception none
	 */

	public void processInData(byte[] buf) {
		/*
		 * the received parameters should not be assigned as global
		 * variables form so that these values won't clash with the
		 * global variables that we want to send out.
		 */
		int URL_len = 0;

		ByteArrayInputStream byteStream = new ByteArrayInputStream(buf);
		DataInputStream dataStream = new DataInputStream(byteStream);

		 try {

			obj_id = dataStream.readInt();
			color = dataStream.readByte() & 255;
			URL_len = (int)dataStream.readByte();
			byte URLbuf[] = new byte[URL_len];
			dataStream.read(URLbuf, 0, URL_len);
			imageURL = new String(URLbuf, 0);
			x1 = dataStream.readUnsignedShort();
			y1 = dataStream.readUnsignedShort();

			System.out.println("%%%% receiving image parameters :");
			imageWidth = dataStream.readUnsignedShort();
			//System.out.println(" imageWidth = "+ dataStream.readUnsignedShort());
			imageHeight = dataStream.readUnsignedShort();

			System.out.println(" imageWidth = "+ imageWidth);
			System.out.println(" imageHeight = "+ imageHeight);

		} catch(java.io.IOException e) {

			System.out.println("IOException in reading Obj_type: " + e);
		}

		System.out.println(" imageURL = |"+imageURL+"|");

		draw();
	}

	/**
	 * return type of the object
	 *
	 *@return type
	 *@exception none
	 */

	public int getType() {
		return type;
	}

	public int getObjID() {
		return obj_id;
	}

}
