package jp.ac.kyutech.mns.ist;

import java.awt.event.KeyEvent;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeMap;

import jp.ac.kyutech.mns.ist.sheetmap.MatrixHolder;
import edu.umd.cs.piccolo.PCamera;
import edu.umd.cs.piccolo.activities.PActivity;
import edu.umd.cs.piccolo.util.PBounds;

public class LayoutAbstract {
	PCamera camera;
//	ArrayList<LayoutContent> sorted;
	MatrixHolder<LayoutContent> matrix;
	int rownum_or_colnum = -1;
	public LayoutAbstract(PCamera cam){
		camera = cam;
		
//		sorted = new ArrayList<LayoutContent>();
		matrix = new MatrixHolder<LayoutContent>();
	}
	//カーソルキーで上下左右するときに，次のフォーカスを探す
//	public LayoutContent getNext(int cur, int offset){
//		int size = sorted.size();
//		int expect = cur + offset;
//		if (size <= expect) {
//			if (cur == size-1) return null; else return sorted.get(size-1);
//		} else if (expect < 0){
//			if (cur == 0) return null; else return sorted.get(0);
//		} else {
//			return sorted.get(expect);
//		}
//	}
	public LayoutContent getUDLR(int keyCode, LayoutContent currentFocus){
		LayoutContent lc = matrix.getUDLR(keyCode, currentFocus);
		if (lc == null && keyCode == KeyEvent.VK_LEFT){
			lc = matrix.getPreviousRowTail(currentFocus);
		}
		if (lc == null && keyCode == KeyEvent.VK_RIGHT){
			lc = matrix.getNextRowHead(currentFocus);
		}
		return lc;
	}

	public void layout(int wait, LayoutTarget target){
		class LayoutTask extends TimerTask{
			ArrayList<LayoutContent> cnt;
			LayoutTask(ArrayList<LayoutContent> _cnt){ cnt = _cnt; }
			public void run(){
				ArrayList<PActivity> palist = move(cnt);
				long mtime = System.currentTimeMillis();
				if (palist == null) return;
				for (PActivity pact : palist) if (pact != null) pact.setStartTime(mtime);
			}
		}
		Timer t = new Timer();
		t.schedule(new LayoutTask(target.getLayoutContents()), wait);
		//カーソルキー移動用の配列追加
//		sorted.clear();
//		sorted.addAll(target.getLayoutContents());
	}
	//縦方向にならべるレイアウト
	public ArrayList<PActivity> move(ArrayList<LayoutContent> cnt){
		int varticalNum = getBestFitLayoutV(cnt, camera.getViewBounds(), 0, 0);
		ArrayList<PActivity> palist = new ArrayList<PActivity>();

		int ix=0,iy=0;
		double x = 0, y = 0, xmax = 0, w = 0;
		double xgap = 0, ygap = 0;
		int varticalCount = 0;
		matrix.removeAll();
		for(LayoutContent pn: cnt){
			if (!pn.hasContent()) continue;
			PActivity pa = pn.animateToPositionScaleRotation(x, y, 1, 0, 1000);
			//			System.out.println("x y "+x+" "+y);
			matrix.put(ix, iy, pn);
			palist.add(pa);
			y += pn.getFullBounds().getHeight() + ygap;
			iy++;
			//			x += pn.getFullBoundsReference().getWidth() + xgap;
			if (xmax < pn.getFullBounds().getWidth()) xmax = pn.getFullBounds().getWidth();
			varticalCount++;
			if (varticalCount == varticalNum){
				varticalCount = 0;
				w = w + xmax + xgap;
				x = w;
				y = 0;
				xmax = 0;
				ix++;
				iy=0;
			}
		}
		return palist;
	}
	public Rectangle2D maxContent(ArrayList<LayoutContent> cnt){
		Rectangle2D maximumDim = null;
		double maxDimSq = 0;
		for(LayoutContent fr: cnt){
			Rectangle2D temp = fr.getFullBounds();
			double sq = temp.getWidth()*temp.getHeight();
			if (maxDimSq < sq){
				maxDimSq = sq;
				maximumDim = temp;
			}
		}
		return maximumDim;
	}
	public PBounds contentregion(LayoutTarget target){
		ArrayList<LayoutContent> cnt = target.getLayoutContents();
		int varticalNum = getBestFitLayoutV(cnt, camera.getViewBounds(), 0, 0);
		PBounds returnPB = new PBounds();
		double x = 0, y = 0, xmax = 0, w = 0;
		double xgap = 0, ygap = 0;
		int varticalCount = 0;
		for(LayoutContent pn: cnt){
			if (!pn.hasContent()) continue;
			if (returnPB != null) {
				PBounds aPB = new PBounds(pn.mysize());
				aPB.setOrigin(x,y);
				returnPB.add(aPB);
			}
			y += pn.getFullBounds().getHeight() + ygap;
			//			x += pn.getFullBoundsReference().getWidth() + xgap;
			if (xmax < pn.getFullBounds().getWidth()) xmax = pn.getFullBounds().getWidth();
			varticalCount++;
			if (varticalCount == varticalNum){
				varticalCount = 0;
				w = w + xmax + xgap;
				x = w;
				y = 0;
				xmax = 0;
			}
		}
		return returnPB;
	}
	public int getBestFitLayoutV(Collection<LayoutContent> rects2,
			Rectangle2D availableScreenSize, double xgap, double ygap) {
		ArrayList<Rectangle2D> dims = new ArrayList<Rectangle2D>();
		for(LayoutContent fr: rects2){
			dims.add(fr.mysize());
		}

		int num = dims.size();
		double parentrate = availableScreenSize.getWidth()/availableScreenSize.getHeight();
		if (Double.isNaN(parentrate)) {
			parentrate = 1.66;
		}
//		System.out.println("LayoutAbst Parent "+parentrate);
		TreeMap<Double,Integer> resultRates = new TreeMap<Double,Integer>();

		for(int i=1;i<=num;i++){
			double fitrate = fitrateV(dims, i, xgap, ygap);
			resultRates.put(Math.abs(parentrate - fitrate), i);
//			System.out.println(i+"/"+num+" "+Math.abs(parentrate - fitrate)+" "+fitrate+" parent="+parentrate+"  fitrateV");
		}
		ArrayList<Integer> intres = new ArrayList<Integer>(resultRates.values());
		if (intres.size()>0) rownum_or_colnum = intres.get(0);
//		System.out.println("LayAB 採用"+rownum_or_colnum);
		return rownum_or_colnum;
	}
	public double fitrateV(ArrayList<Rectangle2D> boxes, int varticalNum, double xgap, double ygap){	
		double x = 0, y = 0, w = 0, h = 0;
		int varticalCount = 0;
		for(Rectangle2D pn: boxes){
			y += pn.getHeight() + ygap;
			if (x < pn.getWidth()) x = pn.getWidth();
			varticalCount++;
			if (varticalCount == varticalNum){
				w += x + xgap;
				if (h < y) h = y;
				varticalCount = 0;
				y = 0;
				x = 0;
			}
		}
		w += x + xgap;
		if (h < y) h = y;
		return w/h;	
	}
	public double fitrateH(ArrayList<Rectangle2D> boxes, int horizontalNum, double xgap, double ygap){	
		double x = 0, y = 0, w = 0, h = 0;
		int horizonCount = 0;
		for(Rectangle2D pn: boxes){
			x += pn.getWidth() + xgap;
			if (y < pn.getHeight()) y = pn.getHeight();
			horizonCount++;
			if (horizonCount == horizontalNum){
				h += y + ygap;
				if (w < x) w = x;
				horizonCount = 0;
				y = 0;
				x = 0;
			}
		}
		h += y + ygap;
		if (w < x) w = x;
		return w/h;	
	}

//	public double fitrateHH(ArrayList<Rectangle2D> boxes, int horizontalNum, double xgap, double ygap){	
//		double x = 0, y = 0, w = 0, h = 0;
//		int horizonCount = 0;
//		//		System.out.print("Try "+horizontalNum);
//		for(Rectangle2D pn: boxes){
//			x += pn.getWidth() + xgap;
//			if (y < pn.getHeight()) y = pn.getHeight();
//			horizonCount++;
//			if (horizonCount == horizontalNum){
//				h += y + ygap;
//				if (w < x) w = x;
//				horizonCount = 0;
//				y = 0;
//				x = 0;
//			}
//		}
//		h += y + ygap;
//		if (w < x) w = x;
//		return w/h;	
//	}
	

}
