package jp.ac.kyutech.mns.ist.filter;

import java.awt.Color;
import java.awt.Paint;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Hashtable;

import jp.ac.kyutech.mns.ist.ShortStroke;
import jp.ac.kyutech.mns.ist.SimpleATN;
import jp.ac.kyutech.mns.ist.ConfigWindow;
import jp.ac.kyutech.mns.ist.util.FileReadWriter;
import edu.umd.cs.piccolo.util.PBounds;

public class RegionSSFilter extends BaseSSFilter {

	public static Color[] filterColor;
	//                   丁寧さ度合い(1-5),フィルタ
	public static Hashtable<Integer,RegionSSFilter> rssf;
	static {
		filterColor = new Color[6];
		filterColor[1] = new Color(Color.HSBtoRGB(0.0f, 0.6f, 0.8f));
		filterColor[2] = new Color(Color.HSBtoRGB(0.15f, 0.6f, 0.8f));
		filterColor[3] = new Color(Color.HSBtoRGB(0.3f, 0.6f, 0.8f));
		filterColor[4] = new Color(Color.HSBtoRGB(0.45f, 0.6f, 0.8f));
		filterColor[5] = new Color(Color.HSBtoRGB(0.6f, 0.6f, 0.8f));
		rssf = new Hashtable<Integer, RegionSSFilter>();
	}

	//１つめの整数はペン番号，２つめの整数はシート番号（シートを特定する場合は1-6，特定しない場合は0）
	Hashtable<Integer,Hashtable<Integer,ArrayList<RegionSS>>> regions;
	/**
	 * 
	 */
	private static final long serialVersionUID = 5109648666686785855L;
	public static void saveBeforeExit() {
		for(RegionSSFilter sf: rssf.values()){
			sf.exportregions();
		}
	}
	public static void loadAfterLectureLoad(){
		//リセット
		rssf.clear();
		importregions("neat",SimpleATN.theapp.openingLectureid);
	}

	public static void importregions(final String _basefilename, final String _lecnum){
		//regionファイルのフォーマット：pen sheet x y w h 
		//                           0-6 
		File homedir = new File(System.getProperty("user.dir")); //起動ディレクトリを取得
		File[] all = homedir.listFiles(new FilenameFilter() { //起動ディレクトリ直下の，一部のファイルを取得
			@Override
			public boolean accept(File dir, String name) {
				//				System.out.println(name);
				if (name.startsWith("lec_"+_lecnum+"_"+_basefilename)) return true;
				return false;
			}
		});
		for(File f: all){
			//ファイル名の最後の数字を抽出=>これがneatnessになる
			String fname = f.getName();
			String[] sep2 = fname.split("_");
			int neatness = Integer.parseInt(sep2[3]);
			ArrayList<String> data = FileReadWriter.getLinesList(f.getName());
			//data には，ファイルの中身が1行ずつ，はいってくる
			for(String line: data){
				String[] sep = line.split(" ");
				int pennum = Integer.parseInt(sep[0]);
				int sheetnum = Integer.parseInt(sep[1]);
				double x = Double.parseDouble(sep[2]);
				double y = Double.parseDouble(sep[3]);
				double w = Double.parseDouble(sep[4]);
				double h = Double.parseDouble(sep[5]);
				ConfigWindow.configWin.filter.addRegionFilterByFile(pennum,sheetnum,new Rectangle2D.Double(x, y, w, h),neatness,_lecnum);
			}
		}
	}

	public void resetRegions(){
		if (regions == null) regions = new Hashtable<Integer,Hashtable<Integer,ArrayList<RegionSS>>>();
		regions.clear();
	}
	public String info;
	//必要に応じて，初期化を行いつつ領域を登録する
	public void addRegion(int pen, int sht, RegionSS pb){
		Hashtable<Integer,ArrayList<RegionSS>> penHash = regions.get(pen);
		if (penHash == null){
			penHash = new Hashtable<Integer, ArrayList<RegionSS>>();
			regions.put(pen, penHash);
		}
		ArrayList<RegionSS> regionlist = penHash.get(sht);
		if (regionlist == null){
			regionlist = new ArrayList<RegionSS>();
			penHash.put(sht, regionlist);
		}
		regionlist.add(pb);
		pb.setParent(regionlist);//あとで削除できるため，おぼえる
		pb.setFilter(this);//あとで削除したときにcountを減らす必要があるため，おぼえる
		count++;
		updateInfo();
	}
	public void remove(RegionSS region){
		count--;
		updateInfo();
	}

	String basefilename;
	String lecnum;
	int neatness;
	int count = 0;
	public RegionSSFilter(String _basefilename, String _lecnum, int _neatness){
		basefilename = _basefilename;
		lecnum = _lecnum;
		neatness = _neatness;
		resetRegions();//0-6に対応するアレイリストを初期化しておく
		updateInfo();
	}
	public void updateInfo(){
		info = "["+basefilename+" "+neatness+"] lec="+lecnum+"  count="+count;
	}
	public void exportregions(){
		ArrayList<String> outbuffer = new ArrayList<String>();//出力用のバッファ
		for(int pennum: regions.keySet()){
			for(int sheetnum: regions.get(pennum).keySet()){
				ArrayList<RegionSS> regionlist = regions.get(pennum).get(sheetnum);
				for(RegionSS pb: regionlist){
					outbuffer.add(pennum+" "+sheetnum+" "+pb.getX()+" "+pb.getY()+" "+pb.getWidth()+" "+pb.getHeight());//一行の文字列を作成しバッファに追加
				}
			}
		}
		//ここまでで，outbufferに出力内容が蓄えられた
		FileReadWriter.putLines("lec_"+lecnum+"_"+basefilename+"_"+neatness+"_.txt", outbuffer);//上書き保存！（追記ではない）
		//注：改行コードはputLinesメソッドが自動的に追加する
	}

	/**
	 * ここに，単独チェックでのピックアップ条件を書く
	 * @param ss
	 */
	public boolean doesPickUp(ShortStroke ss){
		int pen = ss.penid;
		int sheet = ss.paperid;
		//まず，特定シートの条件にマッチするかチェック
		if (regions.get(pen) != null){
			ArrayList<RegionSS> regionlist = regions.get(pen).get(sheet);
			if (regionlist != null) {
				for(RegionSS pb2: regionlist){
					PBounds pb = pb2.getBounds();
					if (pb.contains(ss.getBounds())){ //フィルタの領域が，筆記の領域を完全に覆っていたら
						return true;
					}
				}
			}
		}
		//つぎに，特定のペンで全シートに対応する領域チェック
		if (regions.get(pen) != null){
			ArrayList<RegionSS> regionlist = regions.get(pen).get(0);

			if (regionlist != null) {
				for(RegionSS pb2: regionlist){
					PBounds pb = pb2.getBounds();
					if (pb.contains(ss.getBounds())){ //フィルタの領域が，筆記の領域を完全に覆っていたら
						return true;
					}
				}
			}
		}
		//つぎに，全ペン，全シートに対応する領域チェック
		if (regions.get(0)!=null){
			ArrayList<RegionSS> regionlist = regions.get(0).get(0);
			if (regionlist != null) {
				for(RegionSS pb2: regionlist){
					PBounds pb = pb2.getBounds();
					if (pb.contains(ss.getBounds())){ //フィルタの領域が，筆記の領域を完全に覆っていたら
						return true;
					}
				}
			}
		}
		return false; //どれにもマッチしなかったら，falseをかえす
	}

	/**
	 * ここに，ペアチェックでのピックアップ条件をかく
	 * @param ss1
	 * @param ss2
	 * @return
	 */
	public boolean doesPickUpByPair(ShortStroke ss1, ShortStroke ss2){
		if (doesPickUp(ss1)&&doesPickUp(ss2)){
			if (ss2.id-ss1.id==1) return true; //連続して書いていたらtrue
		}
		return false;
	}
	public Paint getColor() {
		return RegionSSFilter.filterColor[neatness];
	}

	public void action(String name){
		if (name.equals("hide") || name.equals("show") ){
			for(Hashtable<Integer,ArrayList<RegionSS>> penHash :regions.values()){
				for(ArrayList<RegionSS> regionlist: penHash.values()){
					for(RegionSS region: regionlist){
						region.setVisible(name.equals("show"));
					}
				}
			}
		} else if (name.equals("check")){
			this.sieve(new BaseSSAction());
		} else if (name.equals("sieve")){
			this.sieve(new SieveSSAction(neatness));
		} else if (name.equals("sievePair")){
			this.sieveByPair(new SievePairSSAction());
		}
	}
}
