/* 	Copyright 2008 Maximum Processing Inc
	
	ABOUT THIS SCRIPT

	DEPENDENCIES
	  1. logging.js

	
	Change Log
 	Created 11/25/2008 Nathan Townsend
*/







RulesMaker = new function() {
    try {


        /* -------------- PRIVATE VARIABLES --------------  */

        var _preProcess = null;             // the div containing the pre process rule elements

        var _postProcess = null;            // the div containing the post process rule elements

        var _currentComponentID = null;       // a stored reference to the component being editied
				
				var selected = new Array();




        /* -------------- PUBLIC METHODS --------------  */
        return {
				
					  DeleteComponent: function()
						{
						
						  if(_currentComponentID == null)
							  return;
						  
							var ctrl = RuleStorage.GetComponent(_currentComponentID);
							
							ctrl.Delete();
							
							ctrl = null;
						  
							RuleXML.DeleteComponent(_currentComponentID);
							
							RuleStorage.Remove(_currentComponentID);
							
							_currentComponentID = null;
							
							Graphics.Refresh();
							
						},

						AddComponent: function(Component)
						{
						  try{
							
                var Ref = $(Component).attr("ref");
								
                    var ctrl = NewComponent(Ref);

                    RuleXML.AddComponent(ctrl.GetNode());

                    var Icon = new RuleIcon();
										
										Icon.Load(ctrl);

                    Icon.AppendTo( $("#" + RuleXML.CurrentProcess) );
										
										ctrl.SetIcon(Icon);
										
										var _nam = (RuleXML.CurrentProcess == "preproc") ? "preprocessicons" : "postprocessicons";

										ContextMenu.Add(Icon.GetImage(), RulesMaker.GetIconContextMenu, _nam);

                    RuleStorage.AddComponent(ctrl, ctrl.GetID());
								
              } catch (err) { Log.Add("RulesMaker.DropComponent", err, LogType.Error); }																
						},

		        Enable: function() {
						  try{
							
								$(".RuleToolbar img").unbind("dblclick.RulesMaker").bind("dblclick.RulesMaker", function(){
								  RulesMaker.AddComponent($(this));
								})
							
                AddFeatures(_preProcess);

                AddFeatures(_postProcess);
								
								Undo.Reset();								
								
              } catch (err) { Log.Add("RulesMaker.Enable", err, LogType.Error); }								
            },

            Disable: function() {
						  try{
							
								$(".RuleToolbar img").unbind("dblclick.RulesMaker");
							
                RemoveFeatures(_preProcess);

                RemoveFeatures(_postProcess);

                RuleStorage.Reset();
								
								_preProcess.html("");
								
								_postProcess.html("");
								
								Graphics.ClearGraphics();
								
								Undo.Reset();

							} catch (err) { Log.Add("RulesMaker.Disable", err, LogType.Error); }
            },
						
						GetCurrentComponent: function()
						{
  							return RuleStorage.GetComponent(_currentComponentID);

  					},
						
						HighlightComponent: function(process, component)
						{
						  try{
  						  if(RuleXML.CurrentProcess != process)
	  						{
		  					  // switch to the process
			  				}
							
  							var ctrl = RuleStorage.GetComponent(component);
  							
  							ctrl.Icon.Highlight();
  							
							} catch(err){Log.Add("RulesMaker.HighlightComponent", err, LogType.Error);}		
						},


            // Sets up the rules maker editor, only call once
            Initialize: function(PreProcessDiv, PostProcessDiv) {
                try {

                    _preProcess = $(PreProcessDiv);

                    _postProcess = $(PostProcessDiv);
										

										Graphics.Initialize(_preProcess.attr("id"), _postProcess.attr("id"));

										$(".RuleToolbar img[ref]").each(function(){
										  var ref = $(this).attr("ref");
											var fn = new Function("return new " + ref + "();");
                      var ctrl = fn();
											$(this).attr("title", ctrl.Title + "\n\n" + ctrl.ToolTip);
										});

										var d = [_preProcess, _postProcess];
										

										for(var i = 0; i<2; i++)
										{
										  d[i].click( function(){ContextMenu.Hide(); });
										  

											d[i].selectable({
  										  filter: "img",
  											selected: function(Event, ui)
  											{
  											  var id = $(ui.selected).attr("id");
  												RulesMaker.AddSelected(id);
  											},
  											start: function(Event, ui)
  											{
  												RulesMaker.ClearSelected();
													ContextMenu.Hide();
  											},
  											
  											stop: function(Event, ui)
  											{
  											  if(RulesMaker.GetSelected().length < 2)
  												{
  												  RulesMaker.ClearSelected();
  												}
  											}									
  											
  										});
										}

										
		
                    Log.Add("RulesMaker.Initialize", "Initialized", LogType.Info);

                } catch (err) { Log.Add("RulesMaker.Initialize", err, LogType.Error); }
            },
						
						AddSelected: function(id)
						{
 							selected.push(id);
						},
						
						ClearSelected: function()
						{
						  try{
							
  							selected = null;
  							
  							selected = new Array();
  							
  							_preProcess.find("img").each(function(){
  							  $(this).removeClass("ui-selected");
  							});
  							
  							_postProcess.find("img").each(function(){
  							  $(this).removeClass("ui-selected");
  							});	
							
              } catch (err) { Log.Add("RulesMaker.ClearSelected", err, LogType.Error); }												
						},
						
						CopySelected: function(boolCut)
						{
						  try{
  						  if(selected.length == 0)
  								selected.push($(ContextMenu.EventComponent).attr("id")); 
  
  						  var xml = "";
  							
  						  for(var i = 0; i<selected.length; i++)
  							{
  							  var id = selected[i];
  								var ret = RuleXML.GetComponent(id);
  								xml += ret;
  							}
  							
  							Global.ClipboardSet(xml);	
  							
  							if(boolCut)
  							  RulesMaker.DeleteSelected();		
								
              } catch (err) { Log.Add("RulesMaker.CopySelected", err, LogType.Error); }						  
						},
						
						DeleteSelected: function()
						{
						  try{
							
  						  if(selected.length ==0)
  								selected.push($(ContextMenu.EventComponent).attr("id")); 
  							
  							var uo = new UndoObject();
								
								uo.AddUndo(RulesMaker.Load, RuleXML.GetVRM().xml);
  						
  						  for(var i = 0; i<selected.length; i++)
  							{
  							  var id = selected[i];
									var ctrl = RuleStorage.GetComponent(id);									
  							  ctrl.Delete();
									ctrl = null;
  								RuleXML.DeleteComponent(id);
									RuleStorage.Remove(id);									
  							}
								
								uo.AddRedo(RulesMaker.Load, RuleXML.GetVRM().xml);
								
								Undo.Add(uo);
  							
  							RulesMaker.ClearSelected();
								
  							Graphics.Refresh();
								
              } catch (err) { Log.Add("RulesMaker.DeleteSelected", err, LogType.Error); }
						},
						
						PasteSelected: function()
						{
						  try{
							
  						  // convert clipboard text into xml
  							var str = "<str>" + Global.ClipboardGet() + "</str>";
  							
  							var xml = $(Utilities.ParseXML(str));
  							
  							// get last component id in the rule proecss + 1
  							var nextID = RuleXML.GetNextComponentNumber();
  							
  							// get difference between last rule id and the lowest id in the xml
  							var n = xml.find("str>c>n");
  							
  							var _lowest = 10000000;
  							n.each(function(){
  								var x = parseInt($(this).text());
  								_lowest = x < _lowest ? x : _lowest; 
  							});
  							
  							var factor = nextID - _lowest;
  							
  							RulesMaker.ClearSelected();
  
  							// loop thorugh xml and add factor to each component number
  							var newSelects = new Array();
  							n.each(function(){
  								var x = parseInt($(this).text()) + factor;
  								$(this).text(x);
  								newSelects.push(x);
  							});
								
								
  							// update jumps & remove if refers to non-pasted element	
                var i = 0;
                
                xml.find("str>c>j").each(function(){	
                  var j = parseInt($(this).text()) + factor;
                
                  if(i=0)
                	  $(this).text( j >= nextID ? j : "");									  
                
                  if(i=1)
                	  $(this).text( j >= nextID ? j : "");									  
  
                	i++;
                });
  
  							// append the xml elements and refresh 
  							RuleXML.AppendXML(xml.find("str>c"));
  							
  							RulesMaker.Load(RuleXML.GetVRM());
  
  							selected = newSelects;
  							for(var i = 0; i < selected.length; i++)
  							{
  							  var id = selected[i];
  								var ctrl = RuleStorage.GetComponent(id);
  								var img = ctrl.Icon.GetImage();
  								img.addClass("ui-selected");
  							}
  							
              } catch (err) { Log.Add("RulesMaker.PasteSelected", err, LogType.Error); }							
						},
						
						GetSelected: function()
						{
						  return selected;
						},
						
						GetCanvasContextMenu: function()
						{
						  try{
  						  var items = new ContextMenuItems();
  							items.Add("Save", function(){ PropertiesEditor.Save() });
  							items.Add("Close", function(){ PropertiesEditor.Disable() });							
  							
  							try{
                  var cd = Global.ClipboardGet();
    							if((cd.substring(0, 3) == "<c>") && (cd.substring(cd.length - 4) == "</c>")) 
    							  items.Add("Paste", function(){ RulesMaker.PasteSelected() });
  							}catch(err){ return null;}
  							
  							if(Undo.CanUndo())
  							  items.Add("Undo", function(){ Undo.Undo() });
  								
  							if(Undo.CanRedo())
  							  items.Add("Redo", function(){ Undo.Redo() });
  														
  							return items.GetHTML();
								
              } catch (err) { Log.Add("RulesMaker.GetCanvasContextMenu", err, LogType.Error); }							
						},
						
						GetIconContextMenu: function()
						{
						  try{
  						  var items = new ContextMenuItems();
  							items.Add("Cut", function(){RulesMaker.CopySelected(true)});
  							items.Add("Copy", function(){RulesMaker.CopySelected(false)});
  							items.Add("Delete", function(){ RulesMaker.DeleteSelected() });
  
  							return items.GetHTML();
							
              } catch (err) { Log.Add("RulesMaker.GetIconContextMenu", err, LogType.Error); }							
						},


            // called from Communication.EditorRequest passing in the vrm xml document
            Load: function(xml) {
                try {
								
										if(typeof xml == "string")
										  xml = Utilities.ParseXML(xml);
								
                    RuleXML.Load(xml);
										
										RuleStorage.Reset();
										
										var notes = RuleXML.GetEditorNotes();
										
										Global.SetNotes(notes);
										
										$("#EditorNotes #save").removeAttr("disabled");
										
										var _currentProc = RuleXML.CurrentProcess;

									  RulesMaker.SetCurrentProcess("preproc");
                    RuleHelper.LoadComponents(RuleXML.GetPreProcessXML(), _preProcess);
										
									  RulesMaker.SetCurrentProcess("postproc");
                    RuleHelper.LoadComponents(RuleXML.GetPostProcessXML(), _postProcess);
										
										ContextMenu.Add("#" + _preProcess.attr("id") + ">img", RulesMaker.GetIconContextMenu, "preprocessicons");
										ContextMenu.Add("#" + _postProcess.attr("id") + ">img", RulesMaker.GetIconContextMenu, "postprocessicons");
										
										ContextMenu.Add("#" + _preProcess.attr("id"), RulesMaker.GetCanvasContextMenu, "preprocesscanvas");
										ContextMenu.Add("#" + _postProcess.attr("id"), RulesMaker.GetCanvasContextMenu, "postprocesscanvas");
										
										RulesMaker.SetCurrentProcess(_currentProc);
										
                    RulesMaker.Enable();
										
										ShowCanvasHeight();
										
										Graphics.Refresh();
										
                    Log.Add("RulesMaker.Load", "Load Succeeded", LogType.Info);

                } catch (err) { Log.Add("RulesMaker.Load", err, LogType.Error); }
            },
						
						Refresh: function()
						{
						  							
							
						},
						
            Save: function() {
                try {
								
                    Communication.EditorUpdate();

                    Log.Add("RulesMaker.Save", "Save Succeeded", LogType.Info);

                } catch (err) { Log.Add("RulesMaker.Save", err, LogType.Error); }
            },
						
						SetCanvasHeight: function()
						{
						  try{
  						  var xml = RuleXML.GetFunctionXML();
  
  						  var preHeight = $("#preproccontainer .RuleSection input").val();
  							
  							_preProcess.css("height", preHeight);
								
								$("#preproccanvas").css("height", preHeight);

								RuleXML.SetCanvasHeight(preHeight, "preHeight");
								
  						  var postHeight = $("#postproccontainer .RuleSection input").val();
  							
  							_postProcess.css("height", postHeight);

								$("#postproccanvas").css("height", postHeight);								

								RuleXML.SetCanvasHeight(postHeight, "postHeight");								
								
								Graphics.Refresh();
								
							}catch(err){Log.Add("RulesMaker.SetCanvasHeight", err, LogType.Error);}			
						},						
						
						SetCurrentProcess: function(ProcessDivID)
						{
						  try{
  						  RuleXML.CurrentProcess = ProcessDivID;
  							Graphics.SetCurrentProcess(ProcessDivID);
  							RuleStorage.SetCurrentProcess(ProcessDivID);
							}catch(err){Log.Add("RulesMaker.SetCurrentProcess", err, LogType.Error);}											
						},

            ShowProperties: function(ID) {
                try {
								
										var ctrl = RuleStorage.GetComponent(ID);
										
										if(ctrl == null)
										  return;
										
                    var properties = ctrl.GetProperties();
										
										PropertiesEditor.SetTitle(ctrl.Ref);
										
										PropertiesEditor.Show(properties, this.DeleteComponent, ctrl.Title);
										
                    _currentComponentID = ID;
										
										Global.EditingTemplate = false;
										
                    Log.Add("RulesMaker.ShowProperties", "Show Properties Succeeded", LogType.Info);

                } catch (err) { Log.Add("RulesMaker.ShowProperties", err, LogType.Error); }
            },
						
						RefreshProperties: function()
						{
						  try{

	  					  this.ShowProperties(_currentComponentID);

							} catch (err) { Log.Add("RulesMaker.RefreshProperties", err, LogType.Error); }	
						},
						
						ComplexArgs: function(GetProperties, AddParam, DeleteParam)
						{
						  this.GetProperties = GetProperties;
							this.AddParam = AddParam;
							this.DeleteParam = DeleteParam;
						}
						

        }






        /* -------------- PRIVATE METHODS --------------  */
        function AddFeatures(div) {
          try {
				

													

          } catch (err) { Log.Add("RulesMaker.AddFeatures", err, LogType.Error); }
        }

        function RemoveFeatures(div) {
            try {

                div = $(div);

            } catch (err) { Log.Add("RulesMaker.RemoveFeatures", err, LogType.Error); }

        }

        function NewComponent(strType) {
            try {

                var ctrl = null;

                var fn = new Function("return new " + strType + "();");

                ctrl = fn();

                if (ctrl == null)
                    Log.Add("RulesMaker.NewComponent", "The component could not be created: type = " + strType, LogType.Warning);

                ctrl.Create();

                return ctrl;

            } catch (err) {err.description += "; Type = " + strType;   Log.Add("RulesMaker.NewComponent", err, LogType.Error); }
        }
				
				
				function ShowCanvasHeight() {
				  try{

            var xml = RuleXML.GetFunctionXML();
            
            var preHeight = RuleXML.GetCanvasHeight("preHeight"); 
						
						$("#preproccontainer .RuleSection input").val(preHeight);  // show value in text box
            
            var postHeight = RuleXML.GetCanvasHeight("postHeight");
						
						$("#postproccontainer .RuleSection input").val(postHeight);
						
						RulesMaker.SetCanvasHeight();
            

            } catch (err) { Log.Add("RulesMaker.ShowCanvasHeight", err, LogType.Error); }				
				}


    } catch (err) { Log.Add("RulesMaker", err, LogType.Error); }
}












// Delegates the storage between preprocess and post process 
RuleStorage = new function()
{
  try{
	
	  var PreProcStorage = new Storage();
 
    var PostProcStorage = new Storage();
		
		var CurrentProcess = null;

    this.AddComponent = function(Component, ID) {
      try{

			  CurrentProcess.AddComponent(Component, ID);

      } catch (err) { Log.Add("RuleStorage.AddComponent", err, LogType.Error); }

    }


    this.GetComponent = function(ID) {
      try{

			  return CurrentProcess.GetComponent(ID);
        
      } catch (err) { Log.Add("RuleStorage.GetComponent", err, LogType.Error); }
    }
		
		
		
    this.GetCount = function() {
      try{
			
			  return CurrentProcess.GetCount();
        
      } catch (err) { Log.Add("RuleStorage.GetComponent", err, LogType.Error); }
    }
		
		this.GetItemArray = function()
		{
		  try{
			
			  return CurrentProcess.GetItemArray();
 				
		  } catch (err) { Log.Add("RuleStorage.GetItemArray", err, LogType.Error); }
		}


    this.Remove = function(ID) {
      try{
      
 			  CurrentProcess.Remove(ID);

      } catch (err) { Log.Add("RuleStorage.Remove", err, LogType.Error); }
    }



    this.Reset = function() {
      try {
      
			  PreProcStorage.Reset();
			  PostProcStorage.Reset();
				      
      } catch (err) { Log.Add("RuleStorage.Reset", err, LogType.Error); }
    }
		
		
		this.SetCurrentProcess = function(ProcessDivID)
		{
		  if(ProcessDivID == "preproc")
			  CurrentProcess = PreProcStorage;
			else
			  CurrentProcess = PostProcStorage;
		
		}




  } catch (err) { Log.Add("Storage", err, LogType.Error); }

}

