package jp.ac.kyutech.mns.ist;

import java.awt.Color;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;

import javax.swing.JPopupMenu;

import jp.ac.kyutech.mns.ist.plugin.DefaultPlugin;
import jp.ac.kyutech.mns.ist.plugin.SheetPlugin_Play;
import jp.ac.kyutech.mns.ist.sheetmap.SeatmapController;
import jp.ac.kyutech.mns.ist.util.FadeTimer;
import jp.ac.kyutech.mns.ist.util.MyPImage;
import jp.ac.kyutech.mns.ist.util.MyQueue;
import edu.umd.cs.piccolo.PCanvas;
import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.event.PInputEvent;
import edu.umd.cs.piccolo.event.PInputEventFilter;
import edu.umd.cs.piccolo.nodes.PPath;
import edu.umd.cs.piccolo.nodes.PText;
import edu.umd.cs.piccolo.util.PAffineTransform;

public class Sheet extends PPath {
	private static final long serialVersionUID = 5503641085788469535L;

/**
 * 背景画像を表示しているシート
 */
	static MyQueue<Sheet> pimgShowingSheets;
	/**
	 * 背景画像を表示しているシートの初期化
	 */
	static {
		pimgShowingSheets = new MyQueue<Sheet>();
	}
	/**
	 * 背景画像を表示しているシートの追加と，容量をあふれたときの非表示化
	 * @param s
	 */
	public static void putPImgQueue(Sheet s){
		if (!pimgShowingSheets.hasData(s)) {
			pimgShowingSheets.put(s);
		}
		if (pimgShowingSheets.size()>20){
			Sheet lasts = pimgShowingSheets.get();
			lasts.doshowImage(false);
		}
	}
	
	private Note note;
	PCanvas canvas; //親のキャンバス．ポップアップメニューを出すときに必要
	//	JFrame frame; //親のウィンドウフレーム．ポップアップメニューを出すときに必要
	public int num;
	MyPImage pimg;
	Event_onSheet event_onsheet;
	Event_onSheet_Draw event_onsheet_draw;
	PText printNum;
	PText numPT;
	
	ArrayList<DefaultPlugin> plugins;
	//追加機能分のメニュー
	public void addPluginMenuTo(JPopupMenu menu) {
		for(DefaultPlugin dp: plugins){
			dp.addMenu(menu);
		}
	}
	static Color numPTColor = new Color(255,153,102);
	static Color numPTColorAry[] = new Color[7];
	static {
		int i = 1;
		for(float f=0.02f; f<0.9f; f+=0.15f){
			numPTColorAry[i] = new Color(Color.HSBtoRGB(f, 0.9f, 0.8f));
			i++;
			if (i>6) break;
		}
	}
	public Note getNote(){
		return note;
	}
	/**
	 * シートの背景画像を表示する／非表示にする
	 * @param f
	 */
	public void isshowImage(boolean f){
		if (f) {
			doshowImage(f);
			Sheet.putPImgQueue(this);
		} else {
			
		}
	}
	/**
	 * 実際にシート背景画像の表示・非表示の切り替えを実行する
	 * @param f
	 */
	public void doshowImage(boolean f){
		if (f && pimg == null){
			MyPImage orig = (MyPImage)SimpleATN.theapp.pimages.get(num);
			if (orig == null) return;
			pimg = orig.refClone();
			addChild(pimg);
			pimg.scale(0.89);
			pimg.offset(30,30);
			pimg.setPickable(false);
			pimg.moveToBack();
		} else if (!f && pimg != null){
			pimg.removeFromParent();
			pimg = null;
		}
	}
	/**
	 * このシートに書かれた筆記をかえす
	 * @return
	 */
	public ArrayList<ShortStroke> getAllShortStroke(){
		ArrayList<ShortStroke> temp = new ArrayList<ShortStroke>();
		for(ShortStroke ss: note.getAll()){
			if (ss.paperid == num) temp.add(ss);
		}
		return temp;
	}

	public Sheet(Note parent, int n){
		note = parent;
		num = n;
		canvas = SimpleATN.theapp.getCanvas();
		//シート上でのマウス操作
		event_onsheet = new Event_onSheet(this);
		addInputEventListener(event_onsheet);
		setVisible(false);
		
		event_onsheet_draw = new Event_onSheet_Draw(this);

		//		GradientPaint gp = new GradientPaint(0,0,Color.RED,500,300,Color.YELLOW);
		//		setPaint(gp);
		//		setStrokePaint(null);
		//		setTransparency(0.2f);
		setPaint(Color.white);
		
		numPT = new PText(String.valueOf(num));
		numPT.setScale(70f);
		numPT.setTransparency(0.7f);
		numPT.setTextPaint(numPTColorAry[num]);
		numPT.setOffset(120,0);
		addChild(numPT);
		numPT.moveToFront();
		numPT.setPickable(false);
		numPT.setVisible(false);
		
		plugins = new ArrayList<DefaultPlugin>();
		plugins.add(new SheetPlugin_Play(canvas, this));
		
	}
	public void setDrawMode(boolean f){
		if (f){
			removeInputEventListener(event_onsheet);
			addInputEventListener(event_onsheet_draw);
			event_onsheet_draw.setEventFilter(new PInputEventFilter(InputEvent.BUTTON1_MASK));
		} else {
			removeInputEventListener(event_onsheet_draw);
			addInputEventListener(event_onsheet);
			event_onsheet_draw.setEventFilter(new PInputEventFilter(InputEvent.BUTTON1_MASK));
		}
	}
	public void focus(PInputEvent aEvent){
		//フォーカス
		Rectangle2D globalb = getGlobalBounds();
		SimpleATN.theapp.zoomToBounds(globalb, 1000,"Sheet.focus");
//		canvas.getCamera().animateViewToCenterBounds(globalb, true, 1000);
	}

	public Rectangle2D convert(PPath selection){
		PAffineTransform at = SimpleATN.theapp.getCanvas().getCamera().getViewTransform();
		Rectangle2D globalb = new Rectangle2D.Double();
		at.inverseTransform(selection.getGlobalBounds(), globalb);//cambからglobalbに計算
		Rectangle2D sheetb = this.globalToLocal(globalb);
		return sheetb;
	}
	
	//集約表示 TODO:
	public void collect(PPath selection, int keycode){
		//(1)
		//		System.out.println("sel localtoglobal (b) "+selection.localToGlobal(selection.getBounds()).toString());
		//=(1)	System.out.println("sel bound globalbound "+selection.getGlobalBounds().toString());
		//=(1)		System.out.println("sel bound "+selection.getBounds().toString());
		//=(1)		System.out.println("sel bound cam2layer "+BUtil.convertRtoR(selection.getBounds(), SimpleATN.theapp.canvas.getCamera(), SimpleATN.theapp.canvas.getLayer()).toString());
		//=(1)		System.out.println("sel bound cam2global "+BUtil.convertRtoR(selection.getBounds(), SimpleATN.theapp.canvas.getCamera(), null).toString());
		//=(1)		System.out.println("sel bound cam2cam "+BUtil.convertRtoR(selection.getBounds(), SimpleATN.theapp.canvas.getCamera(), SimpleATN.theapp.canvas.getCamera()).toString());

		//(2)	System.out.println(this.getBounds().toString());
		//=(2)-translate System.out.println("sheet2cam "+BUtil.convertRtoR(this.getBounds(), this, SimpleATN.theapp.canvas.getCamera()).toString());
		//=(2)-translate System.out.println("sheet2layer "+BUtil.convertRtoR(this.getBounds(), this, SimpleATN.theapp.canvas.getLayer()).toString());
		PAffineTransform at = SimpleATN.theapp.getCanvas().getCamera().getViewTransform();
		Rectangle2D globalb = new Rectangle2D.Double();
		at.inverseTransform(selection.getGlobalBounds(), globalb);//cambからglobalbに計算
		Rectangle2D sheetb = this.globalToLocal(globalb);

		if (keycode == KeyEvent.VK_ENTER){
			/*FocusFrame ff =*/ new FocusFrame("Focus ["+num+"] ", SimpleATN.theapp, sheetb, this, false, true);
//			ff.windowMaximize();
//			ff.validate();
//			ff.setVisible(true);
		} else if (keycode == KeyEvent.VK_F){
			/*FocusFrame ff =*/ new FocusFrame("Focus ["+num+"] ", SimpleATN.theapp, sheetb, this, false, false);
//			ff.windowNormalize();
//			ff.validate();
//			ff.setVisible(true);
		} else if (keycode == KeyEvent.VK_R){
			/*FocusFrame ff =*/ new FocusFrame("Focus ["+num+"] ", SimpleATN.theapp, sheetb, this, true, false);
//			ff.validate();
//			ff.toggleFocusReference();
//			ff.setVisible(true);
			FocusFrame.updateFocusReference(this.note.penid);
		} else if (keycode == KeyEvent.VK_M){
			//seatmap
			new SeatmapController(sheetb, SimpleATN.theapp, this.num);
			Note.addSSHandler(ConfigWindow.configWin.draw);
		}
	}
	/**
	 * 印刷前の準備（画像を表示，枠線を消す，ペン番号とシート番号を表示，標準の大きいペン番号を消す）
	 * @param isBefore
	 */
	public void prepare_for_print(boolean isBefore){
		if (isBefore){
			isshowImage(true);
			setStrokePaint(null);
			printNum = new PText(note.penid+"-"+num);
			addChild(printNum);
			printNum.setScale(3f);
			printNum.setOffset(0,-17);
			if (note.isLandscapeMode) {
				printNum.offset(10, 980);//やっぱり左上に出す
				printNum.rotate(-Math.PI/2);
			}
			printNum.setTransparency(0.2f);
			
			numPT.removeFromParent();
			
		} else {
			isshowImage(false);
			setStrokePaint(Color.black);
			addChild(numPT);
		}
	}

	public int getSSSize() {
		@SuppressWarnings("unchecked")
		Collection<PNode> c = getAllNodes();
		int num = 0;
		for(PNode pn: c){
			if (pn instanceof ShortStroke){
				num++;
			}
		}
		return num;
	}
	public void showFadingSheetNum(int keepmsec){
		showFadingMessage(String.valueOf(num), null, numPTColorAry[num], 70f, 0.7f, keepmsec);
	}
	public void showStaticSheetNum(boolean f){
		numPT.setVisible(f);
	}
	
	public void showFadingMessage(String s, Color bc, Color fc, float scale, float trans, int msec){
		PText pt = new PText(s);
		pt.setScale(scale);
		pt.setTransparency(trans);
		pt.setPaint(bc);
		pt.setTextPaint(fc);
		pt.setOffset(120,0);
		pt.setPickable(false);
		addChild(pt);

		new FadeTimer(pt, msec, 1000, false);
	}

	long lastinput = System.currentTimeMillis();
	public void notifySheet() {
//		System.out.println("snum "+num);
		long now = System.currentTimeMillis();
		if (now - lastinput > 5000){
			animateToColor(Color.yellow, 0);
			animateToColor(Color.white, 4000);

			note.queueNotifyMessage(num);
//			showFadingMessage(String.valueOf(num), Color.yellow, numPTColorAry[num], 70f, 0.7f, 5000);
//			showFadingSheetNum(5000);
		}
		lastinput = now;
	}
	public int getNum() {
		return num;
	}
}
