/* $Id: View.java 651 2013-02-08 01:10:55Z ohura $ */
package smart_gs.drawing_tool.view;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import javax.swing.ImageIcon;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import reasoning_web.logical.ResourcePointer;
import smart_gs.GSConstants;
import smart_gs.drawing_tool.ExLine2D;
import smart_gs.logical.Region;


public abstract class View {
	public enum ViewColor {YELLOW, CYAN, MAGENTA, GREEN, TRANSPARENT, OPAQUE}

	public static final int RECTANGLE = 0;
	public static final int MARKER = 1;
	public static final int POLYGON = 2;
	public static final int LINE_SEGMENT = 3;
	public static final int LINE = 4;
	public static final int MEMOPAD = 5;
	public static final int BOOKMARK = 6;
	public static final int ANCHOR = 7;
	
	protected boolean isSelected;
	protected boolean isEmphasized;
	//
	protected boolean isProtected;
	protected boolean isSelectable = true;
	protected Color defaultColor;
	protected Stroke defaultStroke;
	protected Color selectionColor;
	protected Stroke selectionStroke;
	protected Color emphasizeColor;
	protected Stroke emphasizeStroke;
	//
	protected Color protectedColor;
	protected Stroke protectedStroke;
	protected String title;
	
	protected View(){
		this.selectionColor = Color.RED;
		this.selectionStroke = new BasicStroke();
		this.emphasizeColor = Color.RED;
		this.emphasizeStroke = new BasicStroke(5);
		
		Color c = new Color(50,150,100);
		this.protectedColor = c;
		this.protectedStroke = new BasicStroke(2);
		
		this.defaultColor = Color.black;
	}
	
	public abstract void moveBy(Point2D d);
	public abstract boolean contains(Point2D point);
	public abstract View enlargedView(double ratio,double gapX,double gapY);
	public boolean isSelected(){
		return this.isSelected;
	}
	public void setIsSelected(boolean isSelected) {
		this.isSelected = isSelected;
	}
	public void setIsEmphasized(boolean isEmphasized){
		this.isEmphasized = isEmphasized;
	}
	/*
	 *2007/9/13 
	 */
	public void setIsProtected(String protection){
		//kazuhiro kobayashi 10/7
		this.isProtected = protection.equals(Region.PROTECTED);
	}
	
	public final void draw(Graphics2D g){
		Color oldColor = g.getColor();
		Stroke oldStroke = g.getStroke();
		if(this.isEmphasized){
			g.setColor(this.emphasizeColor);
			g.setStroke(this.emphasizeStroke);
		}
		else if(this.isSelected){
			g.setColor(this.selectionColor);
			g.setStroke(this.selectionStroke);
		}
		else if(this.isProtected){
			g.setColor(this.protectedColor);
			g.setStroke(this.protectedStroke);
		}
		else{
			g.setColor(this.defaultColor);
			if(this.defaultStroke != null){
				g.setStroke(this.defaultStroke);
			}
		}
		
		this.drawShape(g);
		g.setColor(oldColor);
		g.setStroke(oldStroke);
	}
	protected abstract void drawShape(Graphics2D g);
	
	public Color getSelectionColor() {
		return this.selectionColor;
	}
	public Stroke getSelectionStroke(){
		return this.selectionStroke;
	}
	public Color getProtectedColor(){
		return this.protectedColor;
	}
	public Stroke getProtectedStroke(){
		return this.protectedStroke;
	}
	public void setSelectionColor(Color color){
		this.selectionColor = color;
	}
	public void setSelectionStroke(Stroke stroke){
		this.selectionStroke = stroke;
	}
	public void setProtectedColor(Color color){
		this.protectedColor = color;
	}
	public void setProtectedStroke(Stroke stroke){
		this.protectedStroke = stroke;
	}
	public abstract Rectangle2D getRectangle2D();

	public final Rectangle getRectangle() {
		Rectangle2D rect = this.getRectangle2D();
		int x = (int)rect.getX();
		int y = (int)rect.getY();
		int width = (int)rect.getWidth();
		int height = (int)rect.getHeight();
		Rectangle r = new Rectangle(x,y,width,height);
		return r;
	}
	public abstract String getTypeString();
	public abstract int getType();
	public abstract void drawLinkedShape(Graphics2D g, Image image);
	public abstract void drawTemporaryShape(Graphics2D g, Image image);
	public abstract Element createXMLElement(Document document);
	public boolean containsInCorner(Point2D point) {
		return false;
	}
	public boolean isResizable() {
		return false;
	}
	public void resize(Point2D d) {
	}

	public boolean isProtected() {
		return this.isProtected;
	}

	public abstract Point getCenterPoint();


	public void setViewColor(ViewColor color) {
		return;
	}
	public static boolean lineContains(ExLine2D line, double breadth, Point2D point) {
		double x1, y1, x2, y2;
		if (line.getP1().getX() < line.getP2().getX()) {
			x1 = line.getP1().getX();
			y1 = line.getP1().getY();
			x2 = line.getP2().getX();
			y2 = line.getP2().getY();
		} else {
			x1 = line.getP2().getX();
			y1 = line.getP2().getY();
			x2 = line.getP1().getX();
			y2 = line.getP1().getY();			
		}
		double d = line.getP1().distance(line.getP2());
		double y = y2 - y1;
		double theta = Math.asin(y/d);
		AffineTransform rotate = AffineTransform.getRotateInstance(theta, x1, y1);
		Rectangle2D rect = new Rectangle2D.Double(x1, y1 - breadth/2, d, breadth);
		Shape shape = rotate.createTransformedShape(rect);
		return shape.contains(point);
	}
	
	public abstract String getTypeStringForDisplay();

	public int getIndex() {
		return 0;
	}

	public String getTitle() {
		if (this.title == null || this.title.equals("")) {
			return "UNTITLED";
		} else {
			return this.title;
		}
	}

	public void setTitle(String title) {
		this.title = title;
	}
	public abstract void drawLinkIcon(Graphics2D g, Image image);
	public abstract void drawTemporaryIcon(Graphics2D g);
	public abstract void drawSelectedIcon(Graphics2D g);
}
