/* $Id: LineSegView.java 747 2013-09-18 11:24:10Z shayashi $ */
package smart_gs.drawing_tool.view;

import java.awt.Color;
import java.awt.Component;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;

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

import smart_gs.GSConstants;
import smart_gs.drawing_tool.ExLine2D;
import smart_gs.drawing_tool.ImageLabel;
import smart_gs.image_search.logical.TextType;
import smart_gs.logical.URICreator;
import sml_editor.logical.LineDirection;

public class LineSegView extends View{
	Color LineSegmentDefaultColor = new Color(0,0,80,80);
	private List<LineView> lineviews;
	private int index;
	private IndexView indexView;
	private LineDirection lineDirection;

	public LineSegView(LineDirection lineDirection, int index){
		this.lineviews = new ArrayList<LineView>();
//		Line_segment color shayashi 2011.05.31
		this.defaultColor = LineSegmentDefaultColor;
		this.selectionColor = Color.red;
		this.index = index;
		this.lineDirection = lineDirection;
//		this.createIndexView(index);
	}
	public LineSegView(List<ExLine2D> exLines, LineDirection lineDirection, int index){
		super();
		this.lineDirection = lineDirection;
		this.lineviews = new ArrayList<LineView>();
		for(int i=0;i<exLines.size();i++){
			this.lineviews.add(new LineView(exLines.get(i)));
		}
		if (exLines.size()>0) {
			this.lineviews.add(new LineView(new ExLine2D(exLines.get(exLines.size()-1).getP2(),exLines.get(0).getP1())));
		}
		//		Line_segment color shayashi 2011.05.31
		this.defaultColor = LineSegmentDefaultColor;
		this.selectionColor = Color.red;
		this.index = index;
		if (this.lineviews.size() != 0) {
			this.createIndexView(index);
		}
	}
	
	public LineSegView(List<ExLine2D> lines, LineDirection lineDirection, boolean isSelected,boolean isEmphasized, boolean isProtected, int index) {
		this(lines, lineDirection, index);
		this.isSelected = isSelected;
		this.isEmphasized = isEmphasized;
		this.isProtected = isProtected;
		this.lineDirection = lineDirection;
	}

	public LineSegView(List<ExLine2D> exLines) {
		super();
		this.lineviews = new ArrayList<LineView>();
		for(int i=0;i<exLines.size();i++){
			this.lineviews.add(new LineView(exLines.get(i)));
		}
		this.lineviews.add(new LineView(new ExLine2D(exLines.get(exLines.size()-1).getP2(),exLines.get(0).getP1())));
		this.defaultColor = LineSegmentDefaultColor;
		this.selectionColor = Color.red;
	}
	
	// changed 2011.01.02 shayashi
	@Override
	public boolean contains(Point2D point) {
		int xpoints[],  ypoints[];
		xpoints = new int[lineviews.size()];
		ypoints = new int[lineviews.size()];
		Polygon polygon;
		for(int i=0;i<this.lineviews.size();i++){
			xpoints[i] = (int)this.lineviews.get(i).getLine().getP1().getX();
			ypoints[i] = (int)this.lineviews.get(i).getLine().getP1().getY();
		}
		polygon = new Polygon(xpoints,ypoints,lineviews.size());
		return polygon.contains(point);
	}
	
	public void addLineView(LineView line){
		this.lineviews.add(line);
	}
	@Override
	public void drawShape(Graphics2D g) {
		if (this.isSelected()) {
			g.setColor(selectionColor);
		}
		for(int i=0;i<this.lineviews.size();i++){
			this.lineviews.get(i).drawShape(g);
		}

	}
	
//	public void drawShape(Graphics2D g, LineSegEditorImageLabel.Show mode) {
//		if (mode == LineSegEditorImageLabel.Show.LINE_AND_INDEX) {
//			this.drawShape(g);
//			this.indexView.drawShape(g);
//		} else if (mode == LineSegEditorImageLabel.Show.LINE) {
//			this.drawShape(g);
//		} 
//	}

	public void drawShapeForImageLabel(Graphics2D g, ImageLabel.Show mode) {
		if (mode == ImageLabel.Show.LINE_AND_INDEX) {
			this.drawShape(g);
			this.indexView.drawShape(g);
		} else if (mode == ImageLabel.Show.LINE) {
			this.drawShape(g);
		} 
	}
	
	public void drawShapeForLineSegImageLabel(
			Graphics2D g,
			smart_gs.drawing_tool.LineSegEditorImageLabel.Show lineSegShowingMode) {
		if (lineSegShowingMode == smart_gs.drawing_tool.LineSegEditorImageLabel.Show.LINE_AND_INDEX) {
			this.drawShape(g);
			this.indexView.drawShape(g);

		} else if (lineSegShowingMode == smart_gs.drawing_tool.LineSegEditorImageLabel.Show.LINE) {
			this.drawShape(g);
		} 
		
	}
	
	@Override
	public int getType() {
		return View.LINE_SEGMENT;
	}
	
	//2011/01/06 kukita
	public String getTypeString() {
		return URICreator.LINE_SEGMENT;
	}

	@Override
	public void moveBy(Point2D d) {
		for(int i=0;i<this.lineviews.size();i++){
			this.lineviews.get(i).moveBy(d);
		}
	}

	@Override
	public View enlargedView(double ratio, double gapX, double gapY) {
		List<ExLine2D> newLines = new ArrayList<ExLine2D>();
		for(int i=0;i<this.lineviews.size();i++){
			LineView line = this.lineviews.get(i);
			line = (LineView)line.enlargedView(ratio,gapX,gapY);
			newLines.add(line.getLine());
		}
		return new LineSegView(newLines,this.lineDirection, this.isSelected,this.isEmphasized, this.isProtected, this.index);
	}
	@Override
	public Rectangle2D getRectangle2D() {
		LineView line1 = this.lineviews.get(0);
		double minX = line1.getMinX(),minY = line1.getMinY(),maxX = line1.getMaxX(),maxY = line1.getMaxY(); 
		for(int i=0;i<this.lineviews.size();i++){
			LineView line = this.lineviews.get(i);
			if(minX > line.getMinX() || minX == -1){
				minX = line.getMinX();
			}
			if(minY > line.getMinY() || minX == -1){
				minY = line.getMinY();
			}
			if(maxX < line.getMaxX() || minX == -1){
				maxX = line.getMaxX();
			}
			if(maxY < line.getMaxY() || minX == -1){
				maxY = line.getMaxY();
			}
		}
		
		return new Rectangle2D.Double(minX,minY,maxX-minX,maxY-minY);
	}

	@Override
	public void drawLinkedShape(Graphics2D g, Image image) {
		if(this.isSelected){
			this.draw(g);
			return;
		};
		for(int i=0;i<this.lineviews.size();i++){
			this.lineviews.get(i).drawLinkedShape(g, image);
		}
	}
	@Override
	public Element createXMLElement(Document document) {
		Element element = document.createElement("view");
		element.setAttribute("type",URICreator.LINE_SEGMENT);
		for(int i=0;i<this.lineviews.size();i++){
			element.appendChild(this.lineviews.get(i).createXMLElement(document));
		}
		return element;
	}

	public static LineSegView restore(Element element, int index) {
		String lineDirectionType = element.getAttribute("LineDirection");
		LineDirection lineDirection;
		if (lineDirectionType.equals("Horizontal")) {
			lineDirection = LineDirection.HORIZONTAL;
		} else if (lineDirectionType.equals("Vertical")) {
			lineDirection = LineDirection.VERTICAL;
		} else {
			System.out.printf("Illegal XML line specification for element %s: %s",element);
			return null;
		}
		LineSegView view = new LineSegView(lineDirection, index);
		NodeList nodes = element.getChildNodes();

		for(int i=0;i<nodes.getLength();i++){
			if(nodes.item(i).getNodeType() == Node.ELEMENT_NODE){
				Element elem = (Element)nodes.item(i);
				String tagname = elem.getNodeName();
				if(tagname.equals("view")){
					LineView line = LineView.restore(elem);
					view.addLineView(line);
				}
			}
		}
		return view;
	}
	@Override
	public Point getCenterPoint() {
		return new Point((int)this.getRectangle2D().getCenterX(),
							(int)this.getRectangle2D().getCenterY());
	}
	@Override
	public String getTypeStringForDisplay() {
		return "LineSegment";
	}
	@Override
	public int getIndex() {
		return this.index;
	}
	
	public void setIndex(int i) {
		this.index = i;		
	}

	private void createIndexView(int index) {
		Point2D cornerPoint;
		Point2D ansPoint;
		if (lineviews.size() == 0) return;
	    ansPoint = lineviews.get(0).getStartPoint();
		if (this.lineDirection == LineDirection.HORIZONTAL) {
			cornerPoint = new Point(this.getMinX(),this.getMinY());
		} else {
			cornerPoint = new Point(this.getMaxX()-5,this.getMinY());
		}
		
		for (LineView lv : lineviews) {
			Point2D start = lv.getStartPoint();
			Point2D end = lv.getEndPoint();
			if (cornerPoint.distance(start) < cornerPoint.distance(ansPoint)) ansPoint = start;
			if (cornerPoint.distance(end) < cornerPoint.distance(end)) ansPoint = end;
		}
		this.indexView = new IndexView(index, (int)ansPoint.getX(), (int)ansPoint.getY());
	}
	private int getMinY() {
		int minY = (int) this.lineviews.get(0).getMinY();
		for (int i = 0; i < this.lineviews.size(); i++) {
			if (minY > (int)this.lineviews.get(i).getMinY()) {
				minY = (int)this.lineviews.get(i).getMinY();
			}
		}
		return minY;
	}
	private int getMinX() {
		int minX = (int) this.lineviews.get(0).getMinX();
		for (int i = 0; i < this.lineviews.size(); i++) {
			if (minX > (int)this.lineviews.get(i).getMinX()) {
				minX = (int)this.lineviews.get(i).getMinX();
			}
		}
		return minX;
	}

	private int getMaxX() {
		int maxX= (int) this.lineviews.get(0).getMaxX();
		for (int i = 0; i < this.lineviews.size(); i++) {
			if (maxX < (int)this.lineviews.get(i).getMaxX()) {
				maxX = (int)this.lineviews.get(i).getMaxX();
			}
		}
		return maxX;
	}
	
	private class IndexView {
		private int index;
		private int x;
		private int y;
		private Rectangle2D rectangle;
		
		public IndexView(int index, int x, int y) {
			this.index = index;
			this.x = x;
			this.y = y;
		}

		protected void drawShape(Graphics2D g) {
			FontMetrics fm = g.getFontMetrics();
			int h = fm.getHeight();
			int ast = fm.getAscent();
			int w = fm.stringWidth(this.index+"");
			int xx = x - w/2;
			int yy = y - h/2;
			rectangle = new Rectangle2D.Double(xx, yy, w + 10, h);
			Color c  = g.getColor();
			g.setColor(new Color(204,255,255));
			g.fill(rectangle);
			g.setColor(Color.BLACK);
			g.draw(rectangle);
			g.drawString(index+"", xx + 5, yy + ast);
			g.setColor(c);
		}
		
		protected Rectangle2D getRectangle2D() {
			return rectangle;
		}
		
		protected int getIndex() {
			return index;
		}
	}

	@Override
	public void drawLinkIcon(Graphics2D g, Image image) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void drawTemporaryIcon(Graphics2D g) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void drawTemporaryShape(Graphics2D g, Image image) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void drawSelectedIcon(Graphics2D g) {
		ImageIcon closeUp = new ImageIcon(GSConstants.ICON_PATH + "region_close_up.png");
		Image closeUpImage = closeUp.getImage();
		Rectangle closeUpImageRectangle = this.closeUpImageRectangle();
		int w2 = (int)closeUpImageRectangle.getWidth();
		int h2 = (int)closeUpImageRectangle.getHeight();
		int x2 = (int)closeUpImageRectangle.getX();
		int y2 = (int)closeUpImageRectangle.getY();
		g.drawImage(closeUpImage, x2, y2, w2, h2, null);		
	}
	
	@Override
	protected Rectangle closeUpImageRectangle() {
		Rectangle rect = this.getRectangle();
		ImageIcon closeUp = new ImageIcon(GSConstants.ICON_PATH + "region_close_up.png");
		Image closeUpImage = closeUp.getImage();
		int w = (int)(closeUpImage.getWidth(null) / 4.5);
		int h = (int)(closeUpImage.getHeight(null) / 4.5);
		int x = (int)(rect.getX()) - (int)(w * (2/3.0));
		int y = (int)(rect.getY()) + (int)(rect.getHeight() - (h * (1/3.0)));
		return new Rectangle(x, y, w, h);
	}
	
}