package smart_gs.logical;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.geom.Point2D;

import smart_gs.drawing_tool.action.DeleteRegionAction;
import smart_gs.drawing_tool.view.BookmarkView;
import smart_gs.drawing_tool.view.MarkerView;
import smart_gs.drawing_tool.view.MemoPadView;
import smart_gs.drawing_tool.view.MemoPadView.Arrow;
import smart_gs.drawing_tool.view.View;
import smart_gs.logical.region.MemoPadRegion;
import smart_gs.util.Pair;
import smart_gs.util.Triple;

public class RegionOperation {

	private Spread parent = null;

	// Kinds of Operations
	public final static int ADD = 0;
	public final static int REMOVE = 1;
	public final static int CHANGE_LOCATION = 2;
	public final static int PROTECT = 3;
	public final static int RELEASE = 4;

	public final static int CHANGE_BOOKMARK_SIZE = 10;
	public final static int CHANGE_BOOKMARK_COLOR = 11;

	public final static int CHANGE_MARKER_BREADTH = 20;
	public final static int CHANGE_MARKER_COLOR = 21;

	public final static int CHANGE_MEMOPAD_COLOR = 30;
	public final static int CHANGE_MEMOPAD_FONTSIZE = 31;
	public final static int CHANGE_MEMOPAD_TEXT = 32;
	public final static int CHANGE_MEMOPAD_DRAW_ARROW = 33;
	public final static int CHANGE_MEMOPAD_DELETE_ARROW = 34;
	public final static int CHANGE_MEMOPAD_MOVE_ARROW = 35;
	public final static int CHANGE_MEMOPAD_RESIZE = 36;


	private int kind = -1;
	private Region region;
	private Object operationData = null;	


	public RegionOperation(int kind, Region region, Object operationData, Spread parent) {
		this.kind = kind;
		this.region = region;
		this.operationData = operationData;
		this.parent = parent;
	}

	public void revert() {
		switch (this.kind) {
		case ADD: 
			if (!(this.operationData instanceof Region)) {
				return;
			} else {
				Region region = (Region)this.operationData;
				this.parent.removeRegion(region);
				region.makeItZombie();
			}
			break;
		case REMOVE: 
			if (!(this.operationData instanceof Region)) {
				return;
			} else {
				Region region = (Region)this.operationData;
				this.parent.addRegion(region);
				region.resuscitate();
			}
			break;
		case CHANGE_LOCATION: 
			if (!(this.operationData instanceof Point2D)) {
				return;
			} else {
				Point2D p = (Point2D)this.operationData;
				this.region.moveRevertBy(p);
			}
			break;
		case PROTECT: 
			if (!(this.operationData instanceof Region)) {
				return;
			} else {
				this.region.setProtection(Region.NORMAL);
				this.region.getView().setIsProtected(Region.NORMAL);
			}
			break;
		case RELEASE: 
			if (!(this.operationData instanceof Region)) {
				return;
			} else {
				this.region.setProtection(Region.PROTECTED);
				this.region.getView().setIsProtected(Region.PROTECTED);
			}
			break;
		case CHANGE_BOOKMARK_SIZE: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object left;
				left = ((Pair<?, ?>) this.operationData).getLeft();
				Double old_size;
				if (left instanceof Double){
					old_size = (Double)left;
					View view = this.region.getView();
					if (view instanceof BookmarkView) {
						((BookmarkView)view).setSize(old_size);
					}
				}
			}
			break;
		case CHANGE_BOOKMARK_COLOR: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object left;
				left = ((Pair<?, ?>) this.operationData).getLeft();
				String old_color;
				if (left instanceof String){
					old_color = (String)left;
					View view = this.region.getView();
					if (view instanceof BookmarkView) {
						((BookmarkView)view).setColorPath(old_color);
					}
				}
			}
			break;
		case CHANGE_MARKER_BREADTH: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object left;
				left = ((Pair<?, ?>) this.operationData).getLeft();
				Integer old_size;
				if (left instanceof Integer){
					old_size = (Integer)left;
					View view = this.region.getView();
					if (view instanceof MarkerView) {
						((MarkerView)view).setBreadth((int)old_size);
					}
				}
			}
			break;
		case CHANGE_MARKER_COLOR: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object left;
				left = ((Pair<?, ?>) this.operationData).getLeft();
				MarkerView.ViewColor old_color;
				if (left instanceof MarkerView.ViewColor){
					old_color = (MarkerView.ViewColor)left;
					View view = this.region.getView();
					if (view instanceof MarkerView) {
						((MarkerView)view).setViewColor((MarkerView.ViewColor)old_color);
					}
				}
			}
			break;
		case CHANGE_MEMOPAD_COLOR: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object left;
				left = ((Pair<?, ?>) this.operationData).getLeft();
				MemoPadView.ViewColor old_color;
				if (left instanceof MemoPadView.ViewColor){
					old_color = (MemoPadView.ViewColor)left;
					View view = this.region.getView();
					if (view instanceof MemoPadView) {
						((MemoPadView)view).setViewColor((MemoPadView.ViewColor)old_color);
					}
				}
			}
			break;
		case CHANGE_MEMOPAD_FONTSIZE: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object left;
				left = ((Pair<?, ?>) this.operationData).getLeft();
				Integer old_size;
				if (left instanceof Integer){
					old_size = (Integer)left;
					View view = this.region.getView();
					if (view instanceof MemoPadView) {
						((MemoPadView)view).setFontSize((int)old_size);
					}
				}
			}
			break;
		case CHANGE_MEMOPAD_TEXT: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object left;
				left = ((Pair<?, ?>) this.operationData).getLeft();
				String old_text;
				if (left instanceof String){
					old_text = (String)left;
					if (this.region instanceof MemoPadRegion) {
						((MemoPadRegion)this.region).setMemoPadText(old_text);
					}
				}
			}
			break;
		case CHANGE_MEMOPAD_DRAW_ARROW: 
			if (!(this.operationData instanceof Arrow)) {
				return;
			} else {
				View view = this.region.getView();
				if (view instanceof MemoPadView) {
					((MemoPadView)view).deleteLastArrow();
				}
			}
			break;
		case CHANGE_MEMOPAD_DELETE_ARROW: 
			if (!(this.operationData instanceof Point2D)) {
				return;
			} else {
				Point2D point = (Point2D)this.operationData;
				View view = this.region.getView();
				if (view instanceof MemoPadView) {
					((MemoPadView)view).addArrow(((MemoPadView)view).arrowTo(point));
				}
			}
			break;
		case CHANGE_MEMOPAD_MOVE_ARROW: 
			if (!(this.operationData instanceof Triple<?,?,?>)) {
				return;
			} else {
				Object fst = ((Triple<?,?,?>)this.operationData).getFirst();
				Object snd = ((Triple<?,?,?>)this.operationData).getSecond();

				Integer index;
				Point2D old_position;
				if (fst instanceof Integer) {
					index = (Integer)fst;
				} else {
					return;
				}
				if (snd instanceof Point2D) {
					old_position = (Point2D)snd;
				} else {
					return;
				}
				View view = this.region.getView();
				if (view instanceof MemoPadView) {
					((MemoPadView)view).arrowMoveBy(index,old_position);
				}
			}
			break;
		case CHANGE_MEMOPAD_RESIZE: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object left;
				left = ((Pair<?, ?>) this.operationData).getLeft();
				Point2D old_point;
				if (left instanceof Point2D){
					old_point = (Point2D)left;
					View view = this.region.getView();
					if (view instanceof MemoPadView) {
						((MemoPadView)view).resize(old_point);
					}
				}
			}
			break;
		}
	}

	public void exectute() {
		switch (this.kind) {
		case ADD: 
			if (!(this.operationData instanceof Region)) {
				return;
			} else {
				Region region = (Region)this.operationData;
				this.parent.addRegion(region);
				region.resuscitate();
			}
			break;
		case REMOVE: 
			if (!(this.operationData instanceof Region)) {
				return;
			} else {
				Region region = (Region)this.operationData;
				this.parent.removeRegion(region);
				region.makeItZombie();
			}
			break;
		case CHANGE_LOCATION: 
			if (!(this.operationData instanceof Point2D)) {
				return;
			} else {
				Point2D p = (Point2D)this.operationData;
				this.region.moveBy(p);
			}
			break;
		case PROTECT: 
			if (!(this.operationData instanceof Region)) {
				return;
			} else {
				this.region.setProtection(Region.PROTECTED);
				this.region.getView().setIsProtected(Region.PROTECTED);
			}
			break;
		case RELEASE: 
			if (!(this.operationData instanceof Region)) {
				return;
			} else {
				this.region.setProtection(Region.NORMAL);
				this.region.getView().setIsProtected(Region.NORMAL);
			}
			break;
		case CHANGE_BOOKMARK_COLOR: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object right;
				right = ((Pair<?, ?>) this.operationData).getRight();
				String new_color;
				if (right instanceof String){
					new_color = (String)right;
					View view = this.region.getView();
					if (view instanceof BookmarkView) {
						((BookmarkView)view).setColorPath(new_color);
					}
				}
			}
			break;
		case CHANGE_BOOKMARK_SIZE: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object right;
				right = ((Pair<?, ?>) this.operationData).getRight();
				Double new_size;
				if (right instanceof Double){
					new_size = (Double)right;
					View view = this.region.getView();
					if (view instanceof BookmarkView) {
						((BookmarkView)view).setSize(new_size);
					}
				}
			}
			break;
		case CHANGE_MARKER_COLOR: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object right;
				right = ((Pair<?, ?>) this.operationData).getRight();
				MarkerView.ViewColor new_color;
				if (right instanceof MarkerView.ViewColor){
					new_color = (MarkerView.ViewColor)right;
					View view = this.region.getView();
					if (view instanceof MarkerView) {
						((MarkerView)view).setViewColor((MarkerView.ViewColor)new_color);
					}
				}
			}
			break;
		case CHANGE_MEMOPAD_COLOR: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object right;
				right = ((Pair<?, ?>) this.operationData).getRight();
				MemoPadView.ViewColor new_color;
				if (right instanceof MemoPadView.ViewColor){
					new_color = (MemoPadView.ViewColor)right;
					View view = this.region.getView();
					if (view instanceof MemoPadView) {
						((MemoPadView)view).setViewColor((MemoPadView.ViewColor)new_color);
					}
				}
			}
			break;
		case CHANGE_MARKER_BREADTH: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object right;
				right = ((Pair<?, ?>) this.operationData).getRight();
				Integer new_size;
				if (right instanceof Integer){
					new_size = (Integer)right;
					View view = this.region.getView();
					if (view instanceof MarkerView) {
						((MarkerView)view).setBreadth((int)new_size);
					}
				}
			}
			break;
		case CHANGE_MEMOPAD_FONTSIZE: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object right;
				right = ((Pair<?, ?>) this.operationData).getRight();
				Integer new_size;
				if (right instanceof Integer){
					new_size = (Integer)right;
					View view = this.region.getView();
					if (view instanceof MemoPadView) {
						((MemoPadView)view).setFontSize((int)new_size);
					}
				}
			}
			break;
		case CHANGE_MEMOPAD_TEXT: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object right;
				right = ((Pair<?, ?>) this.operationData).getRight();
				String new_text;
				if (right instanceof String){
					new_text = (String)right;
					if (this.region instanceof MemoPadRegion) {
						((MemoPadRegion)this.region).setMemoPadText(new_text);
					}
				}
			}
			break;
		case CHANGE_MEMOPAD_DRAW_ARROW: 
			if (!(this.operationData instanceof Arrow)) {
				return;
			} else {
				Arrow arrow = (Arrow)this.operationData;
				View view = this.region.getView();
				if (view instanceof MemoPadView) {
					((MemoPadView)view).addArrow(arrow);
				}
			}
			break;
		case CHANGE_MEMOPAD_DELETE_ARROW: 
			if (!(this.operationData instanceof Point2D)) {
				return;
			} else {
				Point2D point = (Point2D)this.operationData;
				View view = this.region.getView();
				if (view instanceof MemoPadView) {
					((MemoPadView)view).deleteArrow(point);
				}
			}
			break;
		case CHANGE_MEMOPAD_MOVE_ARROW: 
			if (!(this.operationData instanceof Triple<?,?,?>)) {
				return;
			} else {
				Object fst = ((Triple<?,?,?>)this.operationData).getFirst();
				Object thrd = ((Triple<?,?,?>)this.operationData).getThird();

				Integer index;
				Point2D new_position;
				if (fst instanceof Integer) {
					index = (Integer)fst;
				} else {
					return;
				}
				if (thrd instanceof Point2D) {
					new_position = (Point2D)thrd;
				} else {
					return;
				}
				View view = this.region.getView();
				if (view instanceof MemoPadView) {
					((MemoPadView)view).arrowMoveBy(index,new_position);
				}
			}
			break;
		case CHANGE_MEMOPAD_RESIZE: 
			if (!(this.operationData instanceof Pair<?,?>)) {
				return;
			} else {
				Object right;
				right = ((Pair<?, ?>) this.operationData).getRight();
				Point2D new_point;
				if (right instanceof Point2D){
					new_point = (Point2D)right;
					View view = this.region.getView();
					if (view instanceof MemoPadView) {
						((MemoPadView)view).resize(new_point);
					}
				}
			}
			break;
		}	

	}

}
