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

import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.JMenuItem;

import com.ftinc.si.assist.run.Messages;
import com.ftinc.si.assist.run.SnapshotCommandRecord;
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.TestCaseRecord;
import com.ftinc.si.assist.test.TestCommandIF;
import com.ftinc.si.assist.test.TestCommandRecord;
import com.ftinc.si.assist.test.TestLogger;
import com.ftinc.si.assist.test.Tool;
import com.ftinc.si.assist.test.gui.ArgumentEditor;
import com.ftinc.si.assist.test.gui.AssertEditor;
import com.ftinc.si.assist.test.gui.Plugin;
import com.ftinc.si.assist.test.gui.TestCaseEditor;


public class SnapshotPlugin implements Plugin {
	private ObjectRecord[] a_args;
	private AssertRecord a_assert;
	private Integer id_snapshot;

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

	//snapshotは常に最後尾のノードに作られる。
	private void setSnapshotInfo(TestCaseIF cs) {
		TestCaseRecord t_rec = (TestCaseRecord)cs;
		String include_name = cs.getIncludeCase();

		if (t_rec.snapshot > 0 ) {
			//同じTestCaseにsnapshotがある場合。メモリ上から情報を取得する。
			a_args = t_rec.snapshot_Args;
			a_assert = t_rec.snapshot_Assert;
			id_snapshot = t_rec.snapshot;//TestCaseからスナップショットIDをもらう。
			return;
		} else if (include_name != null) {
			//DBから情報を取得する。
			ArrayList<TestCaseRecord> t_list = Tool._db().getTestCaseList(include_name, 0, 0, Tool.group_code, Tool.version);
			if (t_list.size() > 0) {
				String num = Integer.toString(t_list.get(0).snapshot);//TestCaseの最初だけ（Case名はユニークにすべし）見る。snapshotのID
				if (!"0".equals(num)) { //$NON-NLS-1$
					//snapshotがあるとき。
					ArrayList<ObjectRecord> o_list = new ArrayList<ObjectRecord>();
					ObjectRecord o_rec, i_rec = new ObjectRecord(0);
					Integer i_arg = 1;
					i_rec.id = num + "$" + i_arg.toString();
					while ((o_rec = Tool._db().getObjectRecord(i_rec)) != null) {
						o_list.add(o_rec);
						i_arg++;
						i_rec.id = num + "$" + i_arg.toString();
					}
					a_args = o_list.toArray(new ObjectRecord[o_list.size()]);
					a_assert = Tool._db().getAssert(Integer.valueOf(num));
					id_snapshot = Integer.valueOf(num);
				}
			}
		}
		a_args = null;
	}

	@Override
	public int getPriority(TestCaseIF cs, TestCommandIF rec, String stack) {
		setSnapshotInfo(cs);

		if (stack == null && a_args != null) {
			//includeの中にsnapshotが設定されていて、TestCaseの上もしくは空白である時に、メニュー項目追加。
			return 1;//追加
		}
		return 0;
	}

	@Override
	public int initCommand(TestCommandIF cmd) {
		cmd.setClassName("com.ftinc.si.assist.run.SnapshotCommandRecord"); //$NON-NLS-1$

		//static=false, varpos=0
		cmd.setMethod("$replay(" + id_snapshot.toString() + ")", false, 0); //$NON-NLS-1$ //$NON-NLS-2$
		cmd.setReturnType("void"); //$NON-NLS-1$

		//snapshotの引数の数を返す。
		return a_args.length +1;//$0+snapshotの引数の数
	}

	@Override
	public void initArguments(ArgumentIF[] a) {
		for (int i = 1; i < a.length; i++) {
			a[i].setClassName(a_args[i - 1].className); //$NON-NLS-1$
			a[i].setPOJO(a_args[i - 1].isPOJO); //$NON-NLS-1$
			a[i].setStack(a_args[i - 1].stack);
			a[i].setJSON(a_args[i - 1].jSON);
		}
	}

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

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

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

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

	@Override
	public void editArgument(ArgumentIF a, AssertIF ast, String opt) {
		String id = a.getId().replaceFirst("^[0-9]+(\\$.*$)", "$1"); //$NON-NLS-1$ //$NON-NLS-2$
		ArgumentEditor t_ae = new ArgumentEditor(ArgumentEditor.s_owner, (ObjectRecord)a, id); //$NON-NLS-1$ //$NON-NLS-2$
		t_ae.setVisible(true);
	}

	//snapshot用のTestCommandRecordを生成して返す。
	@Override
	public TestCommandIF extendCommand(TestCommandIF a) {
		if ("com.ftinc.si.assist.run.SnapshotCommandRecord".equals(a.getClassName())) { //$NON-NLS-1$
			TestCommandRecord t_a = (TestCommandRecord)a;
			String str_method = t_a.methodName;

			if (str_method.startsWith("$replay")) { //$NON-NLS-1$
				String num = str_method.replaceFirst("^.*\\(([0-9]+)\\).*$", "$1"); //$NON-NLS-1$ //$NON-NLS-2$
				String sid = SnapshotCommandRecord.snapshotID();

				SnapshotCommandRecord t_rec = new SnapshotCommandRecord();
				if (num.equals(sid)) {
					//snapshotは設定通り
					t_rec._cpAttribute(a);
					return t_rec;
				}
				//予想外のsnapshot
				TestLogger.err("Unexpected Snapshot Error: s_id_snapshot=" + sid + Messages.getString("SnapshotPlugin.10") + num + "!!\n");			}
		}
		return null;
	}

	//Assertの内容を設定する。
	public void initAssert(AssertIF ast) {
		AssertRecord t_ast = (AssertRecord)ast;
		t_ast.targetObj = a_assert.targetObj;
		t_ast.criteriaType = a_assert.criteriaType;
		t_ast.criteriaRex = a_assert.criteriaRex;
		t_ast.description = a_assert.description;
	}

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

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

	@Override
	public void editAssert(AssertIF ast, TestCommandIF atd) {
		AssertEditor a_edit = null;
		try {
			a_edit = new AssertEditor(ArgumentEditor.s_owner, (AssertRecord)ast, (TestCommandRecord)atd);
			a_edit.setVisible(true);
		} catch (Exception e) {
			Tool.alertMSG(null, Messages.getString("TestCaseEditor.44") + e.getMessage() + "\n" + Tool.getStackMessage(e, 0, 10)); //$NON-NLS-1$ //$NON-NLS-2$
			return;
		}
	}

	@Override
	public void destroy() {
	}

}
