package com.ftinc.si.assist.test.gui.plugins;

import java.util.HashMap;
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.FakeMethodRecord;
import com.ftinc.si.assist.test.TestCaseIF;
import com.ftinc.si.assist.test.TestCommandIF;
import com.ftinc.si.assist.test.Tool;
import com.ftinc.si.assist.test.gui.MethodEditor;
import com.ftinc.si.assist.test.gui.Plugin;
import com.ftinc.si.assist.test.gui.TestCaseEditor;

public class CodeFairyPlugin implements Plugin {

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


	@Override
	public int getPriority(TestCaseIF cs, TestCommandIF rec, String stack) {
		if (rec != null && "com.ftinc.si.assist.run.CodeFairy".equals(rec.getClassName())) { //$NON-NLS-1$
			if (rec.isStatic() && "prepare".equals(rec.getMethodName())) { //$NON-NLS-1$
				if (stack != null) {
					return 2;//編集：デフォルトのメニューを排除する。編集や再利用など。
				}
			}
		} else if (stack == null) {
			//TestCaseの上もしくは空白
			return 1;//追加
		}
		return 0;
	}

	@Override
	public int initCommand(TestCommandIF cmd) {
		cmd.setClassName("com.ftinc.si.assist.run.CodeFairy"); //$NON-NLS-1$
		cmd.setMethod("prepare", true, 0); //$NON-NLS-1$
		cmd.setReturnType("void"); //$NON-NLS-1$
		return 2;//「$0+最初の引数」の数
	}

	@Override
	public void initArguments(ArgumentIF[] a) {
		for (int i = 1; i < a.length; i++) {
			a[i].setClassName("com.ftinc.si.assist.test.FakeMethodRecord"); //$NON-NLS-1$
		}
	}

	@Override
	public void initArgument(ArgumentIF a, String opt) {
		a.setClassName("com.ftinc.si.assist.test.FakeMethodRecord"); //$NON-NLS-1$
	}

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

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

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

	@Override
	public void editArgument(ArgumentIF a, AssertIF ast, String opt) {
		String[] argtypes = null;
		String cname = null, mname = null, src = null;
		FakeMethodRecord t_f = (FakeMethodRecord) Tool.getObjectfromJSON(FakeMethodRecord.class, a.getJSON());
		if (t_f != null) {//ある程度編集済みの場合
			cname = t_f.className;
			mname = t_f.methodName;
			argtypes = t_f.argTypes;
			src = t_f.source;
		}

		//JSONの中にソースコードを埋め込む時は"を\''に変えているので、元に戻す。
		if (src != null) {
			src = src.replaceAll(Pattern.quote("\\''"), Matcher.quoteReplacement("\"")); //$NON-NLS-1$ //$NON-NLS-2$
		}
		MethodEditor t_br = new MethodEditor(MethodEditor.s_owner, cname, mname, argtypes, src);
		t_br.setTitle(Messages.getString("TestCaseEditor.68")); //$NON-NLS-1$
		t_br.setVisible(true);
		
		FakeMethodRecord t_f2 = t_br.getFakeMethodRecord();
		if (t_f2 != null && t_f2.className.length() > 0 && t_f2.differed(cname, mname, argtypes, src)) {
			//クラス名が空のときはキャンセル。$1の属性はコンストラクタの引数。
			String json = "{\"$1(int)\": 0,\"className\":\"" + t_f2.className + "\","; //$NON-NLS-1$ //$NON-NLS-2$
			json += "\"methodName\":\"" + t_f2.methodName + "\","; //$NON-NLS-1$ //$NON-NLS-2$
			
			json += "\"source\":\"" + t_f2.source.replaceAll(Pattern.quote("\""), Matcher.quoteReplacement("\\''")) + "\","; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
			json += "\"argTypes\":" + t_f2.jsonOfArgTypes() + "}"; //$NON-NLS-1$ //$NON-NLS-2$
			if (t_f2.source != null && t_f2.source.length() > 0) {
			}
			a.setJSON(json);
		}
	}


	//nullは何もしない
	@Override
	public TestCommandIF extendCommand(TestCommandIF a) {
		return null;
	}
	
	//Assertの内容を設定する。
	public void initAssert(AssertIF ast) {
		((AssertRecord)ast).enable = false;
	}


	@Override
	public void editProperties(HashMap<String, String> map) {
	}

	@Override
	public void initProperties(HashMap<String, String> map) {
	}

	@Override
	public void editAssert(AssertIF ast, TestCommandIF atd) {
	}


	@Override
	public void destroy() {
	}

}
