package com.ftinc.si.assist.test.web;

import java.util.HashMap;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JMenuItem;

import com.ftinc.si.assist.run.Messages;
import com.ftinc.si.assist.test.ArgumentIF;
import com.ftinc.si.assist.test.AssertIF;
import com.ftinc.si.assist.test.AssertRecord;
import com.ftinc.si.assist.test.ObjectRecord;
import com.ftinc.si.assist.test.TestCaseIF;
import com.ftinc.si.assist.test.TestCommandIF;
import com.ftinc.si.assist.test.TestCommandRecord;
import com.ftinc.si.assist.test.Tool;
import com.ftinc.si.assist.test.gui.ArgumentEditor;
import com.ftinc.si.assist.test.gui.Plugin;
import com.ftinc.si.assist.test.gui.SimpleTextEditor;
import com.ftinc.si.assist.test.gui.TestCaseEditor;

public class WebDriverPlugin implements Plugin {

	@Override
	public JMenuItem getMenuItem(String s) {
		if (s.equals("addCommand")) { //$NON-NLS-1$
			return TestCaseEditor.getMenuItem(s, Messages.getString("WebDriverPlugin.0"), null, this); //$NON-NLS-1$
		} else if (s.equals("editArg")) { //$NON-NLS-1$
			return TestCaseEditor.getMenuItem(s, Messages.getString("WebDriverPlugin.1"), null, this); //$NON-NLS-1$
		}
		return null;
	}

	@Override
	public int getPriority(TestCaseIF cs, TestCommandIF rec, String stack) {
		//TestCaseがWebであること。
		//このTestCaseの先頭コマンドがサンプル（rec）として渡ってくる。rec==nullなら新規。stack==$0なら編集。
		if (rec != null && "com.ftinc.si.assist.test.web.PagePlayer".equals(rec.getClassName())) { //$NON-NLS-1$
			if ("$0".equals(stack)) { //$NON-NLS-1$
				return 2;
			} else if ("$1".equals(stack)) { //$NON-NLS-1$
				//特殊な引数なので、このプラグインのみが扱えるようにする。
				return 2;
			} else if ("ASSERT".equals(stack)) { //$NON-NLS-1$
				//ASSERTは編集しない。
				return 2;
			} else if (stack == null) {
				//先頭がWeb型コマンドならば、新規コマンドはWebしか作れないようにする。
				return 1;
			}
		} else if (rec == null) {
			//Web型プラグインがあるとき、他のコマンドは不要
			return 1;
		}
		return 0;
	}

	@Override
	public int initCommand(TestCommandIF cmd) {
		cmd.setClassName("com.ftinc.si.assist.test.web.PagePlayer"); //$NON-NLS-1$
		
		//static=false, varpos=0
		cmd.setMethod("play", false, -1); //$NON-NLS-1$ //$NON-NLS-2$
		cmd.setReturnType("java.lang.String"); //$NON-NLS-1$
		
		//snapshotの引数の数を返す。
		return 2;//$0：本体　+　$1=HashMapなので2
	}

	@Override
	public void initArguments(ArgumentIF[] a) {
		for (int i = 0; i < a.length; i++) {
			if (i == 0) {
				a[i].setClassName("com.ftinc.si.assist.test.web.PagePlayer"); //$NON-NLS-1$
				a[i].setStack("$0"); //$NON-NLS-1$
			} else {
				a[i].setClassName("java.util.HashMap"); //$NON-NLS-1$
				
				String t_stack = "$" + Integer.toString(i); //$NON-NLS-1$
				a[i].setStack(t_stack);
				a[i].setJSON("null");//初期値はnullで完成。 //$NON-NLS-1$
			}
		}
	}

	@Override
	public void initArgument(ArgumentIF a, String opt) {
		// 引数を追加することがないので未定義のまま
	}

	@Override
	public int varArgsPos() {
		return -1;
	}

	@Override
	public boolean hasSubject() {
		return true;
	}

	@Override
	public boolean hasAssert() {
		return true;
	}

	@Override
	public void editArgument(ArgumentIF a, AssertIF ast, String opt) {
		//astはDBにはある。initAssertで作っているから。
		AssertRecord t_ast = (AssertRecord)ast;
		
		if (a.getStack().equals("$0")) { //$NON-NLS-1$
			//ページの再生内容を指定する
			String[] crexs = null;
			if (t_ast.criteriaRex != null) {
				crexs = (String[]) Tool.getObjectfromJSON(String[].class, t_ast.criteriaRex);
			}
			//ObjectRecordはエディタの中で更新される。
			PageActionEditor t_ae = new PageActionEditor(ArgumentEditor.s_owner, (ObjectRecord)a, t_ast, crexs); 
			t_ae.setVisible(true);
		} else if (a.getStack().equals("$1")) { //$NON-NLS-1$
			//必要ならば、ブラウザ情報を指定する。
			BrowserSetter t_be = new BrowserSetter(ArgumentEditor.s_owner, (ObjectRecord)a);
			t_be.setVisible(true);
		}
	}

	//Command生成時にAssertは初期化済み
	@Override
	public void initAssert(AssertIF ast) {
		AssertRecord t_ast = (AssertRecord)ast;
		t_ast.criteriaType = "Inspect"; //$NON-NLS-1$
		t_ast.criteriaRex = "[]"; //$NON-NLS-1$
	}

	//プロパティ編集：「key=value」の組を改行でつなげる。
	@Override
	public void editProperties(HashMap<String, String> map) {
		String t_src = ""; //$NON-NLS-1$
		for(Entry<String, String> entry : map.entrySet()) {
			if (t_src.length() > 0) {
				t_src += "\n"; //$NON-NLS-1$
			}
			t_src += entry.getKey() + "=" + entry.getValue(); //$NON-NLS-1$
		}
		SimpleTextEditor t_editor = new SimpleTextEditor(null, t_src, true);//trueはモーダル
		t_editor.setVisible(true);
		
		final Pattern t_pat = Pattern.compile("^([^=]+)=(.+)$"); //$NON-NLS-1$
		Matcher t_m;
		String t_result = t_editor.getText();
		if (t_result != null) {
			String[] t_array = t_result.split("\n", -1); //$NON-NLS-1$
			map.clear();
			for (int i = 0; i < t_array.length; i++) {
				t_m = t_pat.matcher(t_array[i]);
				if (t_m.find()) {
					map.put(t_m.group(1).trim(), t_m.group(2).trim());
				}
			}
		}
	}

	//このプラグインの設定をシステムプロパティに書き込む。Driverのパスなどである。
	@Override
	public void initProperties(HashMap<String, String> map) {
		for(Entry<String, String> entry : map.entrySet()) {
			String t_key = entry.getKey();
			String t_val = entry.getValue();
			
			//約束の短縮パスを展開する。
			if (t_val.startsWith("$LIBDIR")) {
				String t_path = t_val;
				String t_opt = "";
				if (t_path.matches("^([^,]*?)(\\\\,.*)$")) {
					t_path = t_val.replaceFirst("^([^,]*?)(\\\\,.*)$", "$1");
					t_opt = t_val.replaceFirst("^([^,]*?)(\\\\,.*)$", "$2");
				}
				t_val = Tool._libfile(t_path).getAbsolutePath() + t_opt;
			}
			
			System.setProperty(t_key, t_val);
		}
	}
	
	//Web用のTestCommandRecord(AssertのgetResultStringは固定)を生成して返す。
	@Override
	public TestCommandIF extendCommand(TestCommandIF a) {
		if ("com.ftinc.si.assist.test.web.PagePlayer".equals(a.getClassName())) { //$NON-NLS-1$
			WebTestCommandRecord t_a = new WebTestCommandRecord(0);
			TestCommandRecord t_rec = (TestCommandRecord)a;
			t_a.id = a.getId();
			t_a.subject = a.getSubject();
			t_a.className = a.getClassName();
			t_a.methodName = t_rec.methodName;
			t_a.returnType = a.getReturnType();
			t_a.testCase = a.getTestCase();
			t_a.argTypes = t_rec.argTypes;
			t_a.enable = t_rec.enable;
			t_a.argStatus = t_rec.argStatus;
			return t_a;
		}
		return null;
	}

	@Override
	public void editAssert(AssertIF ast, TestCommandIF atd) {
		Tool.alertMSG(ArgumentEditor.s_owner, Messages.getString("WebDriverPlugin.14")); //$NON-NLS-1$
	}
	
	//ブラウザを終了する。
	@Override
	public void destroy() {
		PagePlayer.quit();
	}
}
