/* $Id: UniSelectedState.java 476 2011-12-02 08:52:40Z ohura $ */
package smart_gs.drawing_tool.state;

import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Point2D.Double;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;

import smart_gs.connection.ConnectionCreator;
import smart_gs.drawing_tool.DrawingModeSelectionPopupMenu;
import smart_gs.drawing_tool.ImageLabel;
import smart_gs.drawing_tool.RightClickMenu;
import smart_gs.drawing_tool.SpreadCanvas;
import smart_gs.drawing_tool.action.AddPointAction;
import smart_gs.drawing_tool.action.MemoPadTextAction;
import smart_gs.drawing_tool.drawing_mode.DefaultDrawingMode;
import smart_gs.drawing_tool.drawing_mode.EraserMode;
import smart_gs.drawing_tool.view.MemoPadView;
import smart_gs.drawing_tool.view.View;
import smart_gs.logical.Region;
import smart_gs.logical.LineSegment;
import smart_gs.logical.region.MemoPadRegion;
import smart_gs.reasoning_web.logical.GS_RWElement;
import smart_gs.reasoning_web.swingui.DirectLinkPanel;
import smart_gs.reasoning_web.swingui.GlobalViewPanel;
import smart_gs.reasoning_web.swingui.ReasoningWebFrame;
import smart_gs.swingui.GSMouseEvent;
import smart_gs.swingui.WorkspaceWindow;
import smart_gs.swingui.toolbar.ImageToolBar;
import smart_gs.swingui.toolbar.action.ShowLocalViewAction;

public class UniSelectedState implements State{
	
	private static UniSelectedState singleton = new UniSelectedState();
	
	private boolean markupMovable = false;
	
	private Point start,end;
	private Region selectedRegion;
	
	private boolean selectedRegionMoving;

	private boolean createArrowPointMode = false;
	private boolean deleteArrowPointMode = false;
	private boolean moveArrowPointMode = false;
	
	private UniSelectedState(){
		
	}
	public static UniSelectedState getInstance(){
		return singleton;
	}
	
	//20080715 shimizu wrote
	public boolean getMarkupMovability(){
		return this.markupMovable;
	}
	public void setMarkupMovability(boolean b){
		this.markupMovable = b;
	}
	
	public void mouseClicked(GSMouseEvent e, SpreadCanvas canvas) {
		/* this works only when a region is selected and exclusively on it */
		if(this.selectedRegion == null){
			return;
		}
		View view = this.selectedRegion.getView();
		if(e.getButton() == MouseEvent.BUTTON3){
			rightButtonClickAction(e,canvas);
		}else if(e.getButton() == MouseEvent.BUTTON1){
			if ((e.getClickCount() == 2) && 
					(view.getType() == View.MEMOPAD) && 
					(view.contains(e.getPoint2D()))) {
				new MemoPadTextAction(this.selectedRegion).actionPerformed(e);
			} else if (WorkspaceWindow.getInstance().onlyOneOfAltCtrlShiftIsPressed()) {
				if(WorkspaceWindow.getInstance().isAlt()){
					/* alternative for right button click */
					rightButtonClickAction(e,canvas);
				} else if(WorkspaceWindow.getInstance().isCtrl()){
					DefaultState.getInstance()
					.setMode(DefaultDrawingMode.getInstance());
					ImageToolBar.setModeListItem(ImageToolBar.modelistarray[ImageToolBar.modeNone]);
				}
			}
		}
		canvas.getImageLabel().setCursor(DefaultState.getInstance().getCursor());
	}

	private void rightButtonClickAction (GSMouseEvent e, SpreadCanvas canvas) {
		JPopupMenu menu = new RightClickMenu(this.selectedRegion, canvas, this);
		menu.show(e.getComponent(),e.getOriginalPoint().x,e.getOriginalPoint().y);
		GlobalViewPanel.getInstance().repaint();
	}
	
	public void mouseDragged(GSMouseEvent e, SpreadCanvas canvas) {
		Point2D point = e.getPoint();
		double x = point.getX();
		double y = point.getY();
		double w = canvas.getImageLabel().getImageWidth();
		double h = canvas.getImageLabel().getImageHeight();
		double xx = (x <= 2?2: (x >= w-2? w-2: x));
		double yy = y <= 2?2: (y >= h-2? h-2: y);
		Point2D d = new Point2D.Double(xx, yy);
		if (this.selectedRegion != null) {
			View view = this.selectedRegion.getView();
			if (view.isResizable()) {
				this.selectedRegionMoving = true;
				view.resize(d);
				WorkspaceWindow.setUpdated(true);
			} else if (view.getType() == View.MEMOPAD && this.moveArrowPointMode) {
				int index = ((MemoPadView)view).getIndexOfMovingArrow();
				((MemoPadView)view).arrowMoveBy(index, d);
				WorkspaceWindow.setUpdated(true);
			} else {
				this.end = new Point((int)xx, (int)yy);		
				if((markupMovable ==true && !this.selectedRegion.getView().isProtected())
						|| ((this.selectedRegion.getView().getType() == View.MEMOPAD)
							&& !this.selectedRegion.getView().isProtected())
						|| (this.selectedRegion.getView().getType() == View.BOOKMARK)
							&& !this.selectedRegion.getView().isProtected()
						|| (this.selectedRegion.getView().getType() == View.ANCHOR)
							&& !this.selectedRegion.getView().isProtected()) {
					Point2D p = new Point2D.Double(this.end.x-this.start.x,this.end.y-this.start.y);
					this.selectedRegionMoving = true;
					this.selectedRegion.getView().moveBy(p);
					WorkspaceWindow.setUpdated(true);
				}
				this.start = this.end;
			}
		}
		canvas.getImageLabel().setCursor(DefaultState.getInstance().getCursor());
	}

	public void mouseEntered(GSMouseEvent e, SpreadCanvas canvas) {
		canvas.getImageLabel().setCursor(DefaultState.getInstance().getCursor());
	}

	public void mouseExited(GSMouseEvent e, SpreadCanvas canvas) {
		canvas.getImageLabel().setCursor(DefaultState.getInstance().getCursor());
	}

	public void mouseMoved(GSMouseEvent e, SpreadCanvas canvas) {
		canvas.getImageLabel().setCursor(DefaultState.getInstance().getCursor());
	}

	public void mousePressed(GSMouseEvent e, SpreadCanvas canvas) {

		this.start = e.getPoint();

		// 2011/01/08 kukita
		if (createArrowPointMode) {
			MemoPadView view = (MemoPadView)this.selectedRegion.getView();
			view.addArrow(view.arrowTo(e.getPoint2D()));
			this.createArrowPointMode = false;
			WorkspaceWindow.setUpdated(true);
			return;
		}
		if (deleteArrowPointMode) {
			MemoPadView view = ((MemoPadView)this.selectedRegion.getView());
			view.deleteArrow(e.getPoint());
			this.deleteArrowPointMode = false;
			((MemoPadRegion)this.selectedRegion).setDeleteArrowPointMode(false);
			return;
		}
		
		// begin assignment
		boolean contains = false;
		boolean contains_in_arrow_head = false;
		View view;
		int length = canvas.getCurrentSpread().getRegions().size();
		int indexR = -1;// the index of the region containing the event point
		int indexA = -1;// the index of the region containing the event point in an arrow head
		for (int i = length - 1; i >= 0; i--) {
			view = canvas.getCurrentSpread().getRegions().get(i).getView();
			if (view.contains(e.getPoint())) {
				contains = true;
				indexR = i;
				break;
			} else if (view.getType() == View.MEMOPAD) {
				if (((MemoPadView)view).containsInArrowHead(e.getPoint())) {
					contains_in_arrow_head = true;
					indexA = i;
					break;
				} else if (((MemoPadView)view).containsInArrow(e.getPoint())) {
					contains = true;
					indexR = i;
					break;
				}
			}
		}
		boolean regionIsSelected = (this.selectedRegion != null);
		boolean buttonOne = e.getButton() == MouseEvent.BUTTON1;
		boolean buttonThree = e.getButton() == MouseEvent.BUTTON3;
		// end assignment


		if (buttonOne) {
			// 2011/01/20 kukita
			// If control and alt are down, ignore regions which contain the event point,
			// enabling you to draw a region within regions
			if (contains && WorkspaceWindow.getInstance().isAlt() && e.isControlDown()) {
				if(regionIsSelected){
					this.selectedRegion.getView().setIsSelected(false);
					ReasoningWebFrame.getInstance().getElementsPanel().setElement(null);
					GlobalViewPanel.getInstance().setSelectedElement(null);
					GlobalViewPanel.getInstance().repaint();

					this.selectedRegion = null;
					State state = DefaultState.getInstance();
				    ImageLabel.setState(state);
				    state.mousePressed(e, canvas);
				    return;
				}
				State state = DefaultState.getInstance();
			    ImageLabel.setState(state);
			    state.mousePressed(e, canvas);
			} else

			if (regionIsSelected && contains && e.isControlDown() && e.isShiftDown()) {
				MultiSelectedState state = MultiSelectedState.getInstance();
				ImageLabel.setState(state);
				state.addSelectedRegion(this.selectedRegion);
				state.addSelectedRegion(canvas.getRegion(e.getPoint()));		
			}
			//		Regionが重なっていた場合にShiftキーと同時にクリックすることで選択できる
			else if (buttonOne && contains && e.isShiftDown()){
				if(regionIsSelected){
					this.selectedRegion.getView().setIsSelected(false);
					//2007/10/30 kazuhiro kobayashi
					ReasoningWebFrame.getInstance().getElementsPanel().setElement(null);
					GlobalViewPanel.getInstance().setSelectedElement(null);
					GlobalViewPanel.getInstance().repaint();
				}
				this.selectedRegion = canvas.getAnotherRegion(e.getPoint());
				this.selectedRegion.getView().setIsSelected(true);
				//2007/10/30 kazuhiro kobayashi
				ReasoningWebFrame.getInstance().getElementsPanel().setElement(this.selectedRegion);
				GlobalViewPanel.getInstance().setSelectedElement(this.selectedRegion);
				GlobalViewPanel.getInstance().repaint();
			}
			

			else if (contains) {   //クリックした場所にregionが含まれていた場合
				if(regionIsSelected){ // cancel selection
					this.selectedRegion.getView().setIsSelected(false);
					//2007/10/30 kazuhiro kobayashi
					
					ReasoningWebFrame.getInstance().getElementsPanel().setElement(null);
					GlobalViewPanel.getInstance().setSelectedElement(null);
					GlobalViewPanel.getInstance().repaint();
				}
				
				// select the region which contains the event point
//				this.selectedRegion = canvas.getRegion(e.getPoint());
				this.selectedRegion = canvas.getRegionByIndex(indexR);//2011/01/08 kukita
				this.selectedRegion.getView().setIsSelected(true);
				//2007/10/30 kazuhiro kobayashi
				
				
				if (DefaultState.getInstance().getMode() == EraserMode.getInstance()) {
					EraserMode.getInstance().mousePressed(e,canvas);
					return;
				}
				
				if (this.getSelectedRegion().getView().getType() == View.MEMOPAD) {
					MemoPadView mview = (MemoPadView)this.selectedRegion.getView();
					ImageLabel imageLabel = WorkspaceWindow.getInstance().getSpreadCanvas().getImageLabel();
					double ratio = imageLabel.getRatio();
					double gapX = imageLabel.getGapWidth();
					double gapY = imageLabel.getGapHeight();
					if (mview.containsInCorner(e.getPoint())) {
						mview.setResizeMode(true);
					}
					/* if the event point is contained in the corner of the memopad,
					 * set the memopad to be resizable.
					 * 2010/11 kukita 
					 */

					ReasoningWebFrame.getInstance().getElementsPanel().setElement(this.selectedRegion);
					GlobalViewPanel.getInstance().setSelectedElement(this.selectedRegion);
					GlobalViewPanel.getInstance().repaint();
				}				
			}
			else if (contains_in_arrow_head) {
				if (regionIsSelected) { // cancel selection
					this.selectedRegion.getView().setIsSelected(false);
					//2007/10/30 kazuhiro kobayashi
					
					ReasoningWebFrame.getInstance().getElementsPanel().setElement(null);
					GlobalViewPanel.getInstance().setSelectedElement(null);
					GlobalViewPanel.getInstance().repaint();
				}
				this.setMoveArrowPointMode(true);
				this.selectedRegion = canvas.getRegionByIndex(indexA);
				MemoPadView mview = ((MemoPadView)this.selectedRegion.getView());
				mview.setIsSelected(true);
				mview.setIndexOfMovingArrow(e.getPoint2D());
			}
			
			else if(regionIsSelected){
				this.selectedRegion.getView().setIsSelected(false);
				ReasoningWebFrame.getInstance().getElementsPanel().setElement(null);
				GlobalViewPanel.getInstance().setSelectedElement(null);
				GlobalViewPanel.getInstance().repaint();

				this.selectedRegion = null;
				State state = DefaultState.getInstance();
			    ImageLabel.setState(state);
			    state.mousePressed(e, canvas);
			} else {
				this.selectedRegion = null;
				State state = DefaultState.getInstance();
			    ImageLabel.setState(state);
//			    state.mousePressed(e, canvas);				
			}
		} else if (buttonThree) {			
			// select the region which contains the event point
			if (contains) {
				if(regionIsSelected){ // cancel selection
					this.selectedRegion.getView().setIsSelected(false);
					ReasoningWebFrame.getInstance().getElementsPanel().setElement(null);
					GlobalViewPanel.getInstance().setSelectedElement(null);
					GlobalViewPanel.getInstance().repaint();
				}
				this.selectedRegion = canvas.getRegionByIndex(indexR);//2011/01/08 kukita
				this.selectedRegion.getView().setIsSelected(true);

			} else if (contains_in_arrow_head) {
				if(regionIsSelected){ // cancel selection
					this.selectedRegion.getView().setIsSelected(false);
					ReasoningWebFrame.getInstance().getElementsPanel().setElement(null);
					GlobalViewPanel.getInstance().setSelectedElement(null);
					GlobalViewPanel.getInstance().repaint();
				}
				this.selectedRegion = canvas.getRegionByIndex(indexA);
				this.setMoveArrowPointMode(true);
				MemoPadView mview = ((MemoPadView)this.selectedRegion.getView());
				mview.setIsSelected(true);
				mview.setIndexOfMovingArrow(e.getPoint2D());
			}
		} // 2010/11/28 kukita
		canvas.getImageLabel().setCursor(DefaultState.getInstance().getCursor());
	}


	public void mouseReleased(GSMouseEvent e, SpreadCanvas canvas) {
		this.selectedRegionMoving = true;
		if (this.selectedRegion != null) {
			View view = this.selectedRegion.getView();
			if (view.getType() == View.MEMOPAD) {
				if (((MemoPadView)view).isResizable()) {
					((MemoPadView)view).setResizeMode(false);
				} else if (((MemoPadView)view).getIndexOfMovingArrow() >= 0) {
					((MemoPadView)view).setIndexOfMovingArrow(-1);
					this.moveArrowPointMode = false;
				}
			}
		}
		// 2010/11 kukita
		canvas.getImageLabel().setCursor(DefaultState.getInstance().getCursor());

	}

	public void paint(Graphics g, SpreadCanvas canvas) {

	}
	public Region getSelectedRegion() {
		return this.selectedRegion;
	}
	public boolean isSelectedRegionMoving() {
		return this.selectedRegionMoving;
	}
	public void setCreateArrowPointMode(boolean b) {
		this.createArrowPointMode = b;
	}
	public void setDeleteArrowPointMode(boolean b) {
		this.deleteArrowPointMode = b;
		if (this.getSelectedRegion().getView().getType() == View.MEMOPAD) {
			((MemoPadRegion)this.getSelectedRegion()).setDeleteArrowPointMode(b);
		}
	}
	public void setMoveArrowPointMode(boolean b) {
		this.moveArrowPointMode = b;
	}
	
	//2011/01/21 kukita
	public void setSelectedRegion(Region region) {
		this.selectedRegion = region;
	}
	@Override
	public int getType() {
		return State.UNISELECTED;
	}
	
}
