function BehaviorViewModel(pluginModel, method, id) {
	this.pluginModel = pluginModel;
	this.method = method;
	this.id = id;

	this.getBehaviorName = function() {
		return pluginModel.nickName + "_" + method + "_" + id;
	}
}
/**
 * @param id
 * @param parentId
 * @param childId
 */
function BatchViewModel(id, parentId, childId) {
	this.id = id;
	this.parentId = parentId;
	this.childId = childId;
}
function Behavior(usePlugin, containerId) {
	// var containerId = "useBehaviorList";
	var usePlugin = usePlugin;

	var behaviorMap = new HashMap();
	var behaviorEditorMap = new HashMap();
	var batchMap = new HashMap();

	var index = 1;
	var paramDataCollector = new DataCollector();
	var behavior = this;

	// init tree node container
	jstreeCreate(containerId);

	$("#addBehavior").click(function() {
		// selected node's type
		var selectedNodes = jstreeSelectedNodes(containerId);
		if (!selectedNodes.length) {
			// add page
			showPage();
		} else {
			var currNode = selectedNodes[0];
			var currNodeType = currNode.data;
			if (currNodeType == "page") {
				// add page
				showPage();
			} else if (currNodeType == "batch") {
				// add batch
				showBatch();
			} else {
				// add behavior
				showPluginList();
			}
		}
		$("#selectBehavior").modal('show');
		$("#addBehavior").addClass("clicked");
	});
	$("#insertChildNode").click(function() {

		var selectedNodes = jstreeSelectedNodes(containerId);
		if (!selectedNodes.length) {
			return;
		} else {
			var currNode = selectedNodes[0];
			var currNodeType = currNode.data;
			if (currNodeType == "page") {
				// add batch
				showBatch();
			} else if (currNodeType == "batch") {
				// add behavior
				showPluginList();
			} else {
				// other container behavior;
			}
		}
		$("#selectBehavior").modal('show');
		$("#insertChildNode").addClass("clicked");
	});

	$("#useBehaviorList").bind(
			"select_node.jstree",
			function(node, selected, event) {
				var type = selected.node.data;
				if (type == "page" || type == "batch") {
					$("#insertChildDiv").removeClass("hide");

					updateBehaviorEditors();
				} else {
					$("#insertChildDiv").addClass("hide");

					updateBehaviorEditors();
					$("#behaviorEditor").append(
							behaviorEditorMap.get(selected.node.id));
					$("#behaviorEditor").attr("behavior", selected.node.id);
				}

			});
	$("#selectBehavior")
			.on(
					"click",
					"div[name='behavior_usePlugin']",
					function() {
						var pluginName = $(
								"#selectBehavior input[name='behavior_usePlugin']:checked")
								.val();
						if (pluginName == "page" || pluginName == "batch") {
							return;
						}

						$.post("loadBehaviorList", {
							pluginName : pluginName
						}, function(data) {
							if (!data.success) {
								information("fail");
								return;
							}
							$("#pluginMethod").html("");
							var dataBehaviors = data.behaviors.sort(function(a,
									b) {
								return a.name.localeCompare(b.name);
							});
							createRadioGroupByAttribute(dataBehaviors, "name",
									"name", "name", "method", "pluginMethod")
						});

					});

	$("#selectBehavior #ok")
			.click(
					function() {
						var usePluginId = $(
								"#usePlugins input[name='behavior_usePlugin']:checked")
								.attr("id");
						var method = $(
								"#pluginMethod input[name='method']:checked")
								.val();
						var pluginId = usePluginId.split("_")[2];
						// get add type, insert or add
						var pos;
						if ($("#insertChildNode").hasClass("clicked")) {
							pos = "last";
						} else {
							pos = "after";

						}
						// deal page and batch
						if (pluginId == "page") {
							// add page to web
							createPageViewModel(index, pos);
							jstreeSelectNode(containerId, index);

						} else if (pluginId == "batch") {
							// var batchViewModel = new BatchViewModel(index,
							// -1, -1);
							// batchMap.put(batchViewModel.id, batchViewModel);
							// // add batch to web
							// jstreeCreateNode("useBehaviorList", "batch",
							// "batch",
							// batchViewModel.id, pos);
							createBatchViewModel(index, -1, -1, pos);
							jstreeSelectNode(containerId, index);
						} else {
							if (pluginId == undefined || method == undefined) {
								return;
							}

							// var pluginModel =
							// usePlugin.getUsePluginMap().get(
							// pluginId);
							//
							// var behaviorViewModel = new BehaviorViewModel(
							// pluginModel, method, index);
							//
							// jstreeCreateNode("useBehaviorList",
							// behaviorViewModel.method, behaviorViewModel
							// .getBehaviorName(),
							// behaviorViewModel.id, pos);
							// createBehaviorEditor(behaviorViewModel);
							//
							// // add behavior id to plugin which used
							// pluginModel.behaviors.push(behaviorViewModel);
							// behaviorMap.put(behaviorViewModel.id,
							// behaviorViewModel);

							createBehaviorViewModel(index, pluginId, method,
									pos, index);

						}
						if (pos == "last") {
							$("#insertChildNode").removeClass("clicked");
						} else {
							$("#addBehavior").removeClass("clicked");
						}
						$("#selectBehavior").modal('hide');
						$("#usePlugins").html("");
						$("#pluginMethod").html("");
						index++;
					});
	$("#selectBehavior #cancel").click(function() {
		if ($("#insertChildNode").hasClass("clicked")) {
			$("#insertChildNode").removeClass("clicked")
		} else {
			$("#addBehavior").removeClass("clicked");
			pos = "after";
		}
		$("#selectBehavior").modal('hide');
		$("#usePlugins").html("");
		$("#pluginMethod").html("");
	});
	$("#removeBehavior").click(function() {

		// selected node's type
		var selectedNodes = jstreeSelectedNodes(containerId);
		if (!selectedNodes.length) {
			return;
		}
		var currNode = selectedNodes[0];
		// delete behavior from plugin
		var pluginModel = behaviorMap.get(currNode.id).pluginModel;

		for (var i = 0; i < pluginModel.behaviors; i++) {
			if (pluginModel.behaviors[i].id == currNode.id) {
				pluginModel.behaviors.splice(i, 1);
				break;
			}
		}
		behavior.deleteBehaviorNode(currNode.id);
	});
	this.deleteBehaviorNode = function(behaviorId) {
		behaviorMap.remove(behaviorId);
		behaviorEditorMap.remove(behaviorId);
		// delete node from tree
		jstreeDeleteNode(containerId, behaviorId);
		$("#behaviorEditor").html("");
		$("#behaviorEditor").attr("behavior", "");
	}
	$("#clearBehavior").click(function() {
		$("#insertChildDiv").addClass("hide");
		// delete from pluginModel
		var keys = behaviorMap.getKeys();
		for (var i = 0; i < keys.length; i++) {
			var pluginModel = behaviorMap.get(keys[i]).pluginModel;
			pluginModel.behaviors = [];
		}
		behavior.clearBehaviorNode();

	})
	this.clearBehaviorNode = function() {
		behaviorMap.clear();
		behaviorEditorMap.clear();
		// clear tree
		jstreeClearNode(containerId);
		index = 1;
		$("#behaviorEditor").html("");
		$("#behaviorEditor").attr("behavior", "");
	}
	function updateBehaviorEditors() {
		if ($("#behaviorEditor").attr("behavior") == undefined
				|| $("#behaviorEditor").attr("behavior") == "") {
			return;
		}
		behaviorEditorMap.put($("#behaviorEditor").attr("behavior"), $(
				"#behaviorEditor div:first").clone(true))
		$("#behaviorEditor").attr("behavior", "")
		$("#behaviorEditor").html("");

	}
	function createBehaviorEditor(behaviorModel, selectedId, parameters) {

		var pluginName = behaviorModel.pluginModel.name;
		var methodName = behaviorModel.method;
		var containerFactory = new ContainerFactory();
		$.post("getPluginMethod" + "/" + pluginName + "/" + methodName, {},
				function(data) {
					if (data.success) {
						var methodData = dataTransfer(data.method, parameters);
						var generator = containerFactory.createEditorContainer(
								methodName, "generator", methodData);

						$(generator).addClass("generator");
						behaviorEditorMap.put(behaviorModel.id, generator);
						if (selectedId == behaviorModel.id)
							jstreeSelectNode(containerId, behaviorModel.id);
					} else {
						return;
					}

				});
	}

	function getBehaviorType(pluginName) {
		if (pluginName == "ConstantTimer") {
			return "TIMERBEHAVIOR";
		} else {
			return "USERBEHAVIOR";
		}
	}
	function showPluginList() {
		$("#usePlugins").html("");
		var keys = usePlugin.getUsePluginMap().getKeys();
		for (var i = 0; i < keys.length; i++) {
			var pluginModel = usePlugin.getUsePluginMap().get(keys[i]);
			$("#usePlugins").append(
					createRadio("behavior_plugin_" + pluginModel.id,
							pluginModel.nickName, "behavior_usePlugin",
							pluginModel.name));
		}
	}

	function showPage() {
		$("#usePlugins").html("");
		$("#usePlugins").append(
				createRadio("behavior_plugin_page", "page",
						"behavior_usePlugin", "page"));

	}
	function showBatch() {
		$("#usePlugins").html("");
		$("#usePlugins").append(
				createRadio("behavior_plugin_batch", "batch",
						"behavior_usePlugin", "batch"));

	}

	this.getPages = function() {
		updateBehaviorEditors();
		var treeObj = $("#" + containerId).jstree(true);
		var nodeIds = treeObj.get_node('#').children;
		var idModelMap = new HashMap();
		var tempNodeList = new Array();
		var pages = new Array();

		tempNodeList = tempNodeList.concat(nodeIds);
		var currNodeId;
		while ((currNodeId = tempNodeList.shift()) != undefined) {
			var currNode = treeObj.get_node(currNodeId);
			buildModel(idModelMap, pages, currNode);
			if (treeObj.is_parent(currNodeId)) {
				tempNodeList = tempNodeList.concat(currNode.children);
			}
		}
		return pages;
	}
	function buildModel(idModelMap, pages, currNode) {
		if (currNode.data == "page") {
			var pageModel = new PageModel(currNode.id, new Array());
			pages.push(pageModel);
			idModelMap.put(pageModel.id, pageModel);
		} else if (currNode.data == "batch") {
			var batchViewModel = batchMap.get(currNode.id);
			var batchModel = new BatchModel(batchViewModel.id,
					batchViewModel.parentId, batchViewModel.childId,
					new Array());
			var pageModel = idModelMap.get(currNode.parents[0]);
			pageModel.batches.push(batchModel);
			idModelMap.put(batchModel.id, batchModel);
		} else {
			var behaviorView = behaviorMap.get(currNode.id);
			var behaviorEditor = behaviorEditorMap.get(behaviorView.id);
			var params = paramDataCollector.getUnitParams($(behaviorEditor)
					.find(".editor"));
			var behaviorModel = new BehaviorModel(behaviorView.id,
					behaviorView.pluginModel.id, behaviorView.method,
					getBehaviorType(behaviorView.pluginModel.name), params);

			var batchModel = idModelMap.get(currNode.parents[0]);
			batchModel.behaviors.push(behaviorModel);
			idModelMap.put(behaviorModel.id, behaviorModel);
		}
	}

	this.initBehaviorList = function(pages) {
		// init page, batch, behavior
		for (var i = 0; i < pages.length; i++) {
			// create page
			var page = pages[i];
			createPageViewModel(page.id, "after");
			// update index
			updateIndex(page.id);
			// init batch
			initBatch(page.id, page.batches);
		}
		index += 1;
	}
	function initBatch(parentNode, batches) {
		for (var i = 0; i < batches.length; i++) {
			var batch = batches[i];
			createBatchViewModel(batch.id, batch.parentId, batch.childId,
					"last", parentNode);
			updateIndex(batch.id);
			// init behavior
			initBehavior(batch.id, batch.behaviors);
		}
	}
	function initBehavior(parentNode, behaviors) {
		var selectedId = behaviors[0].id;
		for (var i = 0; i < behaviors.length; i++) {
			var behavior = behaviors[i];
			updateIndex(behavior.id);
			createBehaviorViewModel(behavior.id, behavior.use, behavior.name,
					"last", selectedId, behavior.parameters, parentNode);
		}
	}
	function createPageViewModel(id, pos) {
		jstreeCreateNode(containerId, "page", "page", id, pos);
	}
	function createBatchViewModel(id, parentId, childId, pos, parentNode) {
		var batchViewModel = new BatchViewModel(id, parentId, childId);
		batchMap.put(batchViewModel.id, batchViewModel);
		// add batch to web
		jstreeCreateNode(containerId, "batch", "batch", batchViewModel.id, pos,
				parentNode);
	}
	function createBehaviorViewModel(id, pluginId, method, pos, selectedId,
			parameters, parentNode) {
		var pluginModel = usePlugin.getUsePluginMap().get(pluginId);

		var behaviorViewModel = new BehaviorViewModel(pluginModel, method, id);

		jstreeCreateNode("useBehaviorList", behaviorViewModel.method,
				behaviorViewModel.getBehaviorName(), behaviorViewModel.id, pos,
				parentNode);
		createBehaviorEditor(behaviorViewModel, selectedId, parameters);

		// add behavior id to plugin which used
		pluginModel.behaviors.push(behaviorViewModel);
		behaviorMap.put(behaviorViewModel.id, behaviorViewModel);
	}
	function updateIndex(id) {
		if (index < id) {
			index = id;
		}
	}
}
