﻿<?xml version="1.0" encoding="utf-8" ?> 

<Template Title ="Component Builder">
	<import-style src ="Styles/jsprof.css" id ="jsprof" />
	<import-style src ="Styles/wideselect.css" id ="wideselect" />
	<import-xml src = "Templates/TemplateTools.xml" id = "TemplateTools" />
	<import-xml src = "Fragments/BuilderControls.xml" id = "BuilderControls" />

	<div class="title">Component Description</div>
		<div>
			<select rid ="run_component_as"><option>Scripted</option><option>Declarative</option></select>
			<input type ="button" onclick ="${this}.RunComponent()" value ="Run" />
			<span rid ="component_info">[ Volatile Component ]</span>
		</div>
	<div class ="field">
		<div class = "field_label">
			Name:
		</div>
		<div class = "field_input">
			<input type = "text" class = "input_text" rid = "component_name" />
			<input type = "hidden" value ="0" rid = "component_id" />
		</div>
	</div>
	<div class ="field">
		<div class = "field_label">
			Participation ID: (<i>optional</i>)
		</div>
		<div class = "field_input">
			<input type = "text" class = "input_text" rid = "participation_name" />
		</div>
<!--
		<div class = "field_description">
				Name of <a href ="/projects/engine/api/org.cote.js.transaction.html">Transaction Service</a> transaction this component will use.  The default value is the component name.
		</div>
-->
	</div>
	<div class ="field">
		<div class = "field_label">
			Package:  (<i>optional</i>)
		</div>
		<div class = "field_input">
			<input type = "text" class = "input_text" rid = "package_name" />
		</div>
	</div>

	<div style ="clear:both;" rid = "component_model_container">
			<div class="title">Component Model</div>
			<div ___pointer_marker = "never" component = "wideselect" rid = "component_model">
			</div>
	</div>

	<div>
		<!--
		<input type ="button" value ="T" onclick ="alert(${this}.getProperties().PacketId)" />
		<input type = "button" value = "Debug Parse" onclick ="${this}.DebugParse()" />
		-->
		<input type = "button" value = "Import" onclick ="${this}.LoadComponentText()" />
		<select onchange ="${this}.BuildComponent()" rid = "build_as"><option>Application Component XML</option><option>Application Component Script</option><option>Compiled For Engine Framework</option><option>Selected Function</option></select>
		<input type ="button" value ="New Function" onclick ="${this}.NewComponentFunction()" />
		<span rid ="component_model_controls" style ="display:none;">
			<input type ="button" value ="Deobfuscate" onclick ="${this}.DeobfuscateComponent()" />
			<input type ="button" value ="Update" onclick ="${this}.UpdateComponentMember()" />
			<input type ="button" value ="Remove" onclick ="${this}.RemoveComponentMember()" />
		</span>
		<!--
		<input type ="button"  value = "Build" onclick ="${this}.BuildComponent()" />
		-->
	</div>
	<div><textarea rid ="component_text" wrap ="off" style ="border:0px;margin:0px;width:100%;height:250px;"></textarea></div>
	<embedded-script>
        <![CDATA[
		template_init : function (){
			Hemi.include("hemi.text");
			
			this.scopeHandler("componentmodelclick",0,0,1);
			this.scopeHandler("component_load",0,0,1);
			this.getObjects().component_construct = 0;

			this.refreshBuilderUI();
			this.RefreshComponentBuilder();
			/// this.getProperties().catalog = "DWAC";

			this.GetComponentModel().setResultHandler( this._prehandle_componentmodelclick);
			this.RefreshComponentBuilder();
			this.getProperties().builder_title = "Component Builder";
		},

		template_destroy : function(){
			this._prehandle_componentmodelclick = 0;
			this._prehandle_component_load = 0;
		},
		RefreshComponentBuilder : function(){
			var b = (this.getObjects().component_construct ? 1 : 0);
			this.GetElementByRID("component_name").disabled = (b ? false : true);
			this.GetElementByRID("package_name").disabled = (b ? false : true);
			this.GetElementByRID("participation_name").disabled = (b ? false : true);
			this.GetElementByRID("build_as").disabled = (b ? false : true);
		},
		RunComponent : function(){
			if(!this.getObjects().component_construct) return;
			this.GetElementByRID("build_as").selectedIndex = 1;
			this.BuildComponent();
			var aParams = [this.GetElementByRID("component_name").value, this.GetElementByRID("participation_name").value, this.GetElementByRID("component_text").value,"dwac:" + this.GetDataPath(),this.GetElementByRID("run_component_as").selectedIndex];
			this.RunControl("RunApplicationComponent", aParams);
		},

		LoadObject : function(i){
			this.SetLabel("Loading ...");
			Hemi.xml.setInnerXHTML(this.GetElementByRID("component_info"),"[ Volatile Component ]");
			this.getProperties().component_id = i;
			this.GetElementByRID("build_as").selectedIndex = 0;
			this.ReadData(0, i, this._prehandle_component_load);
		},
		_handle_component_load : function(oService, oSubject, oRequest, oResponse){
			this.SetLabel("");
			if(!oResponse.responseData.length){
				 this.SetLabel("Failed to load component");
				 return;
			}
			var oData = oResponse.responseData[0];
			this.SetDataPath(oData.path);
			var sVal = unescape(oData.value);

			this.GetElementByRID("component_text").value = sVal;

			if(this.LoadComponentText(1)){
				this.GetElementByRID("component_name").value = oData.name;
				this.getObjects().component_construct.id = this.getProperties().component_id;
				Hemi.xml.setInnerXHTML(this.GetElementByRID("component_info"),"Id: " + this.getProperties().component_id + " / Path: " + oData.path);
			}

			this.GetElementByRID("component_id").value = this.getProperties().component_id + "";
	
		},

		DeleteCurrentObject : function(){
			var id = this.getProperties().component_id;
			if(!id){
				 this.SetLabel("Invalid component data id");
				 return;
			}
			if(!confirm("Are you sure you want to delete this component?")) return;
			var oResp = this.DeleteData(["component_id"], id);
			if(oResp.status == true){
					this.ClearComponent();
					/// this.RefreshDWACLists();
			}
			else{
				 this.SetLabel("Failed to delete data #" + id);
			}
		},
		ClearComponent : function(bKeepText){
				this.GetElementByRID("build_as").selectedIndex = 0;
				if(!bKeepText) this.GetElementByRID("component_text").value = "";
				this.GetElementByRID("component_id").value = "0";
				this.GetElementByRID("component_name").value = "";
				this.GetElementByRID("package_name").value = "";
				this.GetElementByRID("participation_name").value = "";
				this.getObjects().component_construct = 0;
				this.getProperties().component_id = 0;
				this.GetComponentModel().clearItems();
				this.SetLabel("");
				Hemi.xml.setInnerXHTML(this.GetElementByRID("component_info"),"[ Volatile Component ]");
				this.RefreshComponentBuilder();
		},
		SaveCurrentObject : function(){
			if(
				 !this.getObjects().component_construct
				 ||
					(
						this.getObjects().component_construct.changes == 0
						&&
						!confirm("No changes detected.  Save anyway?")
					)
			){
				 this.SetLabel("Nothing to do");
				 return;
			}
			if(this.GetElementByRID("build_as").selectedIndex != 0){
				this.GetElementByRID("build_as").selectedIndex = 0;
				this.BuildComponent();
			}
			var sName = this.GetElementByRID("component_name").value;
			var oResp = this.GetNameExists(["component_name","component_id"], sName);
			if(oResp.status == true){
				Hemi.log("Resp Status=" + oResp.status);
				this.SetLabel("The component '" + sName + "' already exists");
				return;
			}
			
			var sTemp = this.GetElementByRID("component_text").value;
			this.GetElementByRID("component_text").value = escape(sTemp);
			
			var aF = ["component_name","participation_name","package_name","component_text","component_id"];
			oResp = 0;
			if(this.getObjects().component_construct.id > 0){
				oResp = this.EditData(aF, this.getObjects().component_construct.id);
			}
			else{
				oResp = this.AddData(aF);
			}
			if(oResp.status){
				this.getObjects().component_construct.changes = 0;
				var sId = oResp.responseId;
				if(!sId || sId.length == 0){
						this.SetLabel("Error retrieving data id");
						this.getObjects().component_construct.id = 0;
				}
				else{
					this.getObjects().component_construct.id = parseInt(sId);
					this.GetElementByRID("component_id").value = sId;
					this.SetLabel("Saved!");
					Hemi.xml.setInnerXHTML(this.GetElementByRID("component_info"),"Id: " + sId + " / Path: " + oResp.responsePath);
					this.SetDataPath(oResp.responsePath);
				}
			}
			else{
					this.SetLabel("Failed to save changes");
			}
			this.GetElementByRID("component_text").value = sTemp;
		},

		CreateNewObject : function(){
				if(this.getObjects().component_construct && this.getObjects().component_construct.changes > 0 && !confirm("Continue?  Changes will be lost.")) return;

				var oW = Hemi.app.createWindow(0,"Templates/NewComponent.xml","NewComponent-" + this.getObjectId(),0,0,{opener_id:this.getObjectId()});
				oW.resizeTo(500,350);
				// Destroy the window when finished
				//
				oW.setHideOnClose(0);
		},
		RemoveComponentMember : function(){
			var o = this.GetComponentModel().getActiveItem();
			var oConstruct = this.getObjects().component_construct;
			if(!o || !oConstruct || !oConstruct.functions[o.data]){
					this.SetLabel("Nothing to do");
					return;
			}
			delete oConstruct.functions[o.data];
			this.GetComponentModel().clearItem(o.index);
			oConstruct.changes++;
			this.GetElementByRID("build_as").selectedIndex = 0;
			this.BuildComponent();
			this.SetLabel("Removed Member - Remember to Save!");
		},
		NewComponentFunction : function(){
				this.NewFunction(this.getObjects().component_construct);
		},
		BuildComponent : function(){
			if(!this.getObjects().component_construct){
				this.SetLabel("Invalid component construct");
				return;	 
			}
			if(this.GetElementByRID("build_as").selectedIndex == 3){
				this.GetElementByRID("build_as").selectedIndex = 0;
			}
			this.GetElementByRID("component_model_controls").style.display = "none";

			this.getObjects().component_construct.name = this.GetElementByRID("component_name").value;
			var sPart = Hemi.text.trim(this.GetElementByRID("participation_name").value);
			var sPack = Hemi.text.trim(this.GetElementByRID("package_name").value);
			//if(sPack.length == 0) sPack = "DemoComponent";
			
			var aBuff = [];	
			
			var bXml = (this.GetElementByRID("build_as").selectedIndex == 0 ? 1 : 0);
			var bCompiled = (this.GetElementByRID("build_as").selectedIndex == 2 ? 1 : 0);
				 
			if(bXml){
				aBuff.push("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<application-components>\n<application-component id=\"" + this.getObjects().component_construct.name + "\"" + (sPart.length > 0 && sPart != this.getObjects().component_construct.name ? " participant-id = \"" + sPart + "\"" : "") + " package-name = \"" + sPack + "\">\n<![CDATA[\n");
			}

			aBuff.push(this.BuildFunctions(this.getObjects().component_construct));

			 
			if(bXml){
				aBuff.push("\n]");
				aBuff.push("]>\n</application-component>\n</application-components>");	 
			}
			var sText = aBuff.join("");
			if(bCompiled){
				 	var oXml = Hemi.xml.getXml("/projects/engine/code/component.dist.xml",null,0,"component_dist",1);

					var sName = this.getObjects().component_construct.name;
					var sBase = 
							 "// " + sPack + "." + sName + "\n"
							 + "// Example: var oComponent = " + sPack + "." + sName + ".newInstance();\n\n"
							 + Hemi.xml.getCDATAValue(oXml.documentElement);

					sBase = sBase.replace(/%APPCOMP_PACKAGE%/gi,sPack)
					sBase = sBase.replace(/%APPCOMP_CLASS%/gi,sName)
					sBase = sBase.replace(/%APPCOMP_LABEL%/gi,"application_component_builder")
					sBase = sBase.replace(/%APPCOMP_USE_FRIENDLY_ID%/gi,1)

					// Reformat the code for the internal AppComp structure
	
					var vTemp, i, aTemp = [];
					
					/* Fix up the user-entered functions */
					vTemp = 0;
					try{
						eval("vTemp = {" + sText + "}");
					}
					catch(e){
						sText = "Failed to extract custom code - " + (e.message ? e.message : e.description);
						this.SetLabel(sText);
						return;
					}

					for(i in vTemp){
						var sKey = i;
						var sValue = vTemp[i].toString();
						sValue = sValue.replace(/^\s*/,"");
						sValue = sValue.replace(/\s*$/,"");
						sValue = sValue.replace(/^function\s*/i,"");
						aTemp.push("n." + i + " = function" + sValue + ";");
					}

					/* Insert user-entered functions into skeleton */
					sBase = sBase.replace(/%APPCOMP_SOURCE_CODE%/gi,"\n" + aTemp.join("\n") + "\n")

							 
					sText = sBase;
			}
			this.GetElementByRID("component_text").value = sText;
		},

		GetComponentModel : function(){
			return this.GetComponentByRID("component_model").GetWideSelect();
		},

		UpdateComponentMember : function(){

			this.UpdateFunction(this.getObjects().component_construct, this.GetElementByRID("component_text").value);
			this.SetLabel("Updated Component - Remember to Save!");
		},
		_handle_componentmodelclick : function(sEvent,oItem){

			if(!oItem || typeof oItem.data != "string" || !this.getObjects().component_construct){
				 this.GetElementByRID("component_text").value = "";
				 return;
			}
			var vFunc = this.getObjects().component_construct.functions[oItem.name];
			if(!vFunc){
				this.GetElementByRID("component_text").value = "Member '" + oItem.name + "' is not constructed.";
				return;
			}
			this.GetElementByRID("component_model_controls").style.display = "inline";
			this.GetElementByRID("build_as").selectedIndex = 3;
			this.GetElementByRID("component_text").value = 
			"/// Notes: Comments before and after members will be lost.\n"
			+ "\n" + this.BuildFunction(vFunc)
			;
			
		},
		DebugParse : function(){
			this.GetElementByRID("build_as").selectedIndex = 0;
			var oX = Hemi.xml.getXml("Gizmos/component.window.xml");
			this.GetElementByRID("component_text").value = Hemi.xml.serialize(oX);
		},
		LoadComponentText : function(bSkipClear){
			var bXml = (this.GetElementByRID("build_as").selectedIndex == 0 ? 1 : 0);
			if(this.getObjects().component_construct && this.getObjects().component_construct.changes > 0 && !confirm("Continue?  Changes will be lost.")) return 0;
			
			if(!bSkipClear) this.ClearComponent(1);
				 
			if(!bXml){
				this.SetLabel("Parsing only available for full application component XML file format.  Select Application Component XML.");
				return 0;
			}
			
			var oXml = null;
			try{
				 oXml = Hemi.xml.parseXmlDocument(this.GetElementByRID("component_text").value);
			}
			catch(e){
				 //alert("Error parsing XML");
				 //return 0;
			}
			if(oXml == null || oXml.documentElement == null){
				this.SetLabel("Failed to parse application component XML");
				return 0;
			}

			var aAppComp = oXml.documentElement.getElementsByTagName("application-component");
			if(aAppComp.length == 0){
				this.SetLabel("No application-component definations found");
				return 0;
			}
			
			if(aAppComp.length > 1){
				this.SetLabel("Multiple application-component definitions found.  Displaying the first component only.  Saving any changes will only save the one component.");
			}
			var oComp = aAppComp[0];
			var n;

			this.GetElementByRID("component_name").value = ((n = oComp.getAttribute("id")) ? n : "");
			this.GetElementByRID("package_name").value = ((n = oComp.getAttribute("package-name")) ? n : "");
			this.GetElementByRID("participation_name").value = ((n = oComp.getAttribute("participant-id")) ? n : "");
			
			var sCodeText = Hemi.xml.getInnerText(oComp);

			this.getObjects().component_construct = this.ParseConstruct(this.GetComponentModel(), sCodeText);
			this.RefreshComponentBuilder();
			 return 1;
		},

		DeobfuscateComponent : function(){
			this.GetElementByRID("component_text").value = this.Deobfuscate(this.GetElementByRID("component_text").value);
		}
		

	]]></embedded-script>
</Template>
