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

public class Rect extends ObjBaseClass implements DrawObject, Cloneable {

	SketchArea parent;
	public int x1, y1, base_x, base_y, old_x1, old_y1;
	public int width, height, old_width, old_height;
	public int type, id;
	public int color = 0;
	public Color[] baseColors = new Color[20];
	Random rand_gen = new Random(System.currentTimeMillis());
	public int obj_id = 0;
	int dist_x, dist_y;

	public Rect(SketchArea parent) {
		super(parent.parent.senderSock, parent.parent.pkt_handler);
		this.parent = parent;
		type = ObjType.RECT;
		baseColors = parent.colorpanel.getBaseColors();
	}

	public Rect(SketchArea parent, int c) {
		super(parent.parent.senderSock, parent.parent.pkt_handler);
		this.parent = parent;
		type = ObjType.RECT;
		baseColors = parent.colorpanel.getBaseColors();
		color = c;
		obj_id = (int) (rand_gen.nextFloat() * 2000);
	}

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

	public boolean mouseDown(int x, int y) {
		base_x = x1 = x;
		base_y = y1 = y;
		return true;

	}

	public boolean mouseUp(int x, int y) {
		width = x - x1;
		height = y - y1;
		//assemble(ObjType.RECT);
		send();
		return true;

	}

	public void send() {
		assemble(ObjType.RECT);
	}

	public boolean mouseDrag(int x, int y) {
		old_height = height;
		old_width = width;
		old_x1 = x1;
		old_y1 = y1;

		if (x - x1 < 0) {
			x1 = x;
			width = base_x - x;
		} else
			 width = x - x1;


		if (y - y1 < 0) {
			y1 = y;
			height = base_y - y;
		} else
			 height = y - y1;

		return true;
	}

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

		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 setBaseDist(Graphics g, int x, int y) {
		dist_x = x - x1;
		dist_y = y - y1;
		erase(g, false);
		//erase_obj_to_move(g);
	}

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

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

	public void clean(Graphics g) {
		g.setColor(parent.getBackground());
		g.drawRect(old_x1, old_y1, old_width, old_height);
	}

	public void erase(Graphics g, boolean send_del_req) {
		g.setColor(parent.getBackground());
		g.drawRect(x1, y1, width, height);
		if (send_del_req == true)
			assemble(ObjType.DELETE);
	}

	public void erase_obj_to_move(Graphics g) {
		g.setColor(parent.getBackground());
		g.drawRect(x1, y1, width, height);
	}

	public void paint(Graphics g) {
		//setPenColor(g, color);
		g.setColor(baseColors[color]);
		g.drawRect(x1, y1, width, height);

	}

	public void draw(int xx1, int yy1, int xx2, int yy2, int col, int obj_id_recvd) {
		x1 = xx1;
		y1 = yy1;
		width = xx2;
		height = yy2;

		this.color = col;
		paint(parent.offscreenG);
		parent.repaint();
		obj_id = obj_id_recvd;
		parent.addStack((Object) this);
	}


	public void setPenColor(Graphics g, int c) {
		g.setColor(baseColors[c]);
	}

	/** assembles Rectangle object's parameters before calling superclass's
	  * BaseClassAssemble function to assemble this resulting packet with
	  * RTP header. This function is called by mouseUp Event.
	  *
	  * @author: Lai-Tee Cheok
	  * @return void
	  **/

	public void assemble(int ObjectType) {
		ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
		DataOutputStream dataStream = new DataOutputStream(byteStream);
		//byte[] data_buf = new byte[5];
		 byte[] data_buf = new byte[1024];
		 System.out.println("len of data_buf in Rect assemble = " + data_buf.length);
		 try {
			dataStream.writeByte(DataType.WBDataType);
			dataStream.writeByte(ObjectType);
			dataStream.writeInt(obj_id);
			if (ObjectType != ObjType.DELETE) {
				dataStream.writeByte((byte) color);
				dataStream.writeShort(x1);
				dataStream.writeShort(y1);
				dataStream.writeShort(width);
				dataStream.writeShort(height);
			}
		} catch(java.io.IOException e) {
			System.out.println("IOException in Rect Object assembling: " + e);
		}
		data_buf = byteStream.toByteArray();
		System.out.println("num. of valide bytes in the bytestream = " + byteStream.size());
		System.out.println("DataType.WBDataType = " + DataType.WBDataType);
		System.out.println("ObjType.RECT = " + ObjType.RECT);
		System.out.println("*************** PARAMERTERS SENT ***********");
		System.out.println("obj_id  = " + obj_id);
		System.out.println("x1  = " + x1);
		System.out.println("y1 = " + y1);
		System.out.println("width  = " + width);
		System.out.println("height  = " + height);
		System.out.println("******************************************");
		BaseClassAssemble(data_buf);
	}

	/** retrieves Rectangle object's parameters from the received packet
	      * and displays on the drawing canvas of the whiteboard.
	      *
	      * @author : Lai-Tee Cheok
	      *
	      * @param buf buffer storing the object's parameters in the form of
	      * byte array.
	      * @return void
	      **/

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

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

		 try {
			obj_id_recvd = (int) (dataStream.readInt());
			col = dataStream.readByte() & 255;
			received_x1 = dataStream.readUnsignedShort();
			received_y1 = dataStream.readUnsignedShort();
			received_width = dataStream.readUnsignedShort();
			received_height = dataStream.readUnsignedShort();
		} catch(java.io.IOException e) {
			System.out.println("IOException in reading Rectangle: " + e);
		}

		draw(received_x1, received_y1, received_width, received_height, col, obj_id_recvd);
	}

	public int getType() {
		return type;
	}

	public int getObjID() {
		return obj_id;
	}

}
