/* $Id: SpreadCanvas.java 475 2011-12-02 08:46:54Z ohura $ */
package smart_gs.drawing_tool;

import java.awt.Component;
import java.awt.Cursor;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JTabbedPane;

import smart_gs.drawing_tool.drawing_mode.BrokenLineMode;
import smart_gs.drawing_tool.state.DefaultState;
import smart_gs.drawing_tool.state.UniSelectedState;
import smart_gs.drawing_tool.view.MemoPadView;
import smart_gs.drawing_tool.view.View;
import smart_gs.logical.LineSegment;
import smart_gs.logical.Region;
import smart_gs.logical.Spread;
import smart_gs.logical.region.AnchorRegion;
import smart_gs.smleditor.swingui.IDATPanel;
import smart_gs.keyboard.action.SelectRegionAction;

@SuppressWarnings("serial")
public class SpreadCanvas extends DrawableCanvas {
	
	private Spread currentSpread = null;
	public ImageLabel imageLabel;
	private ImageIcon imageIcon;
	/*
	 * region、lineが重なっていた場合のために、現在選択されているregion,lineの
	 * List<Region>,List<Line>におけるindexを保存するフィールド
	 */
	private int selectedNumberOfRegion;
	private int selectedNumberOfLine;
	
	// ADD NorthGrid
	private JTabbedPane gsTabbedPane;
	
	
	public SpreadCanvas(){
		super();
		this.getVerticalScrollBar().setUnitIncrement(20);
		this.getHorizontalScrollBar().setUnitIncrement(20);
//		 パネルがキーボードを受け付けるようにする
        setFocusable(true);
        // キーリスナーを登録
        setKeyListener();
//        this.setWheelScrollingEnabled(false);
	}
	public SpreadCanvas(Spread spread,JTabbedPane gsTabbedPane){
		this();
		this.setSpread(spread);
		this.setGsTabbedPane(gsTabbedPane);
	}
	
//	This is for createElemetViewPanel. It does not display 
//	in Editor or Workspace, either. It displays in localViewPanel
//	or ConnectionCreator.
	public SpreadCanvas(Spread spread) {
		// TODO Auto-generated constructor stub
	}

	public void setKeyListener(){
		this.addKeyListener(new SelectRegionAction(this));
	}
	public Point getCornerPoint(){
		return this.getCornerPoint();
	}
	public void setSpread(Spread spread){

		this.setCurrentSpread(spread);
		imageIcon = spread.getImageIcon();
		this.imageLabel = new ImageLabel(this,imageIcon);

		this.setViewportView(this.imageLabel);
	}
	public Spread getSpread(){
		return this.getCurrentSpread();
	}
	
	public JTabbedPane getGsTabbedPane() {
		return gsTabbedPane;
	}
	public void setGsTabbedPane(JTabbedPane gsTabbedPane) {
		this.gsTabbedPane = gsTabbedPane;
	}
	public ImageLabel getImageLabel(){
		return this.imageLabel;
	}
	public void addRegion(Region region) {
		this.imageLabel.addRegion(region);
	}
	public void addTempView(View view){
		this.imageLabel.addTempView(view);
	}
	public void zoomIn() {
		this.imageLabel.zoomIn();
	}
	public void zoomOut(){
		this.imageLabel.zoomOut();
	}

	public void fullSize() {
		this.imageLabel.fullSize();
	}

	public void fitWidth() {
		this.imageLabel.fitWidth(this.getWidth());
	}

	public void fitHeight() {
		this.imageLabel.fitHeight(this.getHeight());
	}

	public boolean containRegions(Point point) {
		List<Region> regions = this.getCurrentSpread().getRegions();
		for(int i=0;i<regions.size();i++){
			if(regions.get(i).contains(new Point2D.Double(point.x,point.y))){
				return true;
			} else if (regions.get(i).getView().getType() == View.MEMOPAD) {
				MemoPadView mview = (MemoPadView)regions.get(i).getView();
				if (mview.containsInArrowHead(point) || mview.containsInArrow(point)) {
					return true;
				} 
			}
		}
		if(ImageLabel.isLineShown() && !(DefaultState.getInstance().getMode() instanceof BrokenLineMode) ){
			List<LineSegment> lines = this.getCurrentSpread().getLines();
			for(int i=0;i<lines.size();i++){
				if(lines.get(i).getView().contains(point)){
					selectLineEvent(i,lines.get(i),point);
					return true;
				}
			}
		}
		return false;
	}
	public void setCenterLocation(Point point){
		this.imageLabel.setCenterLocation(point);
	}

	// 2010/12/15 kukita
	// the selected regions will be moved to the end of the list
	// the search is conducted from tail to head of the list

	public Region getRegion(Point point) {
		List<Region> regions = this.getCurrentSpread().getRegions();
		
		for(int i = regions.size()-1; i>=0; i--){
			View view = regions.get(i).getView();
			boolean is_memopad = view.getType() == View.MEMOPAD;
			boolean contains_in_arrow;
			Point2D point2 = new Point2D.Double(point.x,point.y);
			if (is_memopad) {
				contains_in_arrow = ((MemoPadView)view).containsInArrow(point2);
			} else {
				contains_in_arrow = false;
			}
			if(regions.get(i).contains(point2)
					|| contains_in_arrow){
				regions.add(regions.remove(i));
				this.setSelectedNumberOfRegion(regions.size()-1);
				return regions.get(regions.size()-1);
			}
		}
		if(ImageLabel.isLineShown()){
			List<LineSegment> lines = this.getCurrentSpread().getLines();
			for(int i=0;i<lines.size();i++){
				if(lines.get(i).getView().contains(point)){
					this.selectedNumberOfLine = i;
					return lines.get(i);
				}
			}
		}
		return null;
	}
	
	public Region getRegionByIndex(int index) {
		List<Region> regions = this.getCurrentSpread().getRegions();
		regions.add(regions.remove(index));
		this.setSelectedNumberOfRegion(regions.size() - 1);
		return regions.get(regions.size() - 1);
	}
	
	/*
	 * 同じ位置にあるが現在選択してないregion,lineを選択するメソッド
	 */

	// 2010/12/15 kukita
	public Region getAnotherRegion(Point point){
		List<Region> regions = this.getCurrentSpread().getRegions();
		for(int i = 0; i < regions.size() - 1 ; i++){
			if(i > regions.size() - 1){
				i = 0;
			}
			if(regions.get(i).contains(new Point2D.Double(point.x,point.y))){
				regions.add(regions.remove(i));
				this.setSelectedNumberOfRegion(regions.size() - 1);
				return regions.get(this.getSelectedNumberOfRegion());
			}
		}
		return regions.get(this.getSelectedNumberOfRegion());
	}

	public void clear() {
		this.getViewport().removeAll();	
		this.getCurrentSpread().release();
	}

	// ADD NorthGrid
	public void selectLineEvent(int clickPosition,LineSegment lineSegment,Point point){
		Component component =  gsTabbedPane.getComponent(gsTabbedPane.getSelectedIndex());
		if(component != null){
			if(component instanceof IDATPanel){
				((IDATPanel)component).jumpLinkToText(clickPosition);
			}
		}
	}
	public void protectAllRegions() {
		List<Region> regions = this.getCurrentSpread().getRegions();
		for(int i=0;i<regions.size();i++){
			regions.get(i).setProtection(Region.PROTECTED);
			regions.get(i).getView().setIsProtected(Region.PROTECTED);
		}
	}
	public void releaseAllRegions() {
		List<Region> regions = this.getCurrentSpread().getRegions();
		for(int i=0;i<regions.size();i++){
			regions.get(i).setProtection(Region.NORMAL);
			regions.get(i).getView().setIsProtected(Region.NORMAL);
		}
	}
	public void setCurrentSpread(Spread currentSpread) {
		this.currentSpread = currentSpread;
	}
	public Spread getCurrentSpread() {
		return currentSpread;
	}
	public void setSelectedNumberOfRegion(int selectedNumberOfRegion) {
		this.selectedNumberOfRegion = selectedNumberOfRegion;
	}
	public int getSelectedNumberOfRegion() {
		return selectedNumberOfRegion;
	}
//	public void selectBookmark(Region region) {
//		List<Region> regions = this.currentSpread.getRegions();
//		int index = -1;
//		for (int i = 0; i < regions.size() ; i++) {
//			if (regions.get(i).getURI().equals(region.getURI())) {
//				index = i;
//			}
//		}
//		if (index >= 0) {
//			regions.get(regions.size()-1).getView().setIsSelected(false);
//			regions.add(regions.remove(index));
//			this.setSelectedNumberOfRegion(regions.size()-1);
//			regions.get(regions.size()-1).getView().setIsSelected(true);
//			ImageLabel.setState(UniSelectedState.getInstance());
//		}
//	}
	public void selectRegion(Region region) {
		List<Region> regions = this.currentSpread.getRegions();
		int index = -1;
		for (int i = 0; i < regions.size() ; i++) {
			if (regions.get(i).getURI().equals(region.getURI())) {
				index = i;
			}
		}
		if (index >= 0) {
			regions.get(regions.size()-1).getView().setIsSelected(false);
			regions.add(regions.remove(index));
			this.setSelectedNumberOfRegion(regions.size()-1);
			regions.get(regions.size()-1).getView().setIsSelected(true);
			ImageLabel.setState(UniSelectedState.getInstance());
		}		
	}

}
