(function($) {
  var dashfly = new base2.Package(this, {
    name:    "dashfly",
    version: "1.0",
    exports: "Application,Module,getCallback,getCallbackQuery,registerCallback," +
    		 "unregisterCallback,use,parseXml,ONE_HOUR"
  });
  
  eval(this.imports);
  
  var callbacks = {};
  var now = +new Date();
  var ONE_HOUR = 1000 * 60 * 60;
  var modules = new Array2();
 
//=========================================================================
// Core Applicaton object model
//=========================================================================

  var Application = base2.Base.extend({
	  constructor: function(environment) {
	  	 $.extend(this, {
			theme: 'flora',
			imagePath: '/images/',
			ajaxPath: '/ajaxcall/',
			actionPath: '/',
			urlHelper: new UrlHelper(this)
		 }, environment || {});
	  	 this.services = new Map();
  	  },
  	  
  	  getUrls: function() {
  		  return this.urlHelper;
  	  },
  	  
  	  getService: function(key) {
 		  if (typeof key != "string") {
  			  key = assignID(key);
 		  }
  		  return this.services.get(key); 		  
  	  },
  	  
  	  addService: function(key, service) {
  		  service = service || key;	  
  		  if (typeof key != "string") {
  			  key = assignID(key.constructor);
  		  }
  		  this.services.put(key, service);
  	  },
  	  
  	  removeService: function(key) {
  		  if (typeof key != "string") {
  			  key = assignID(key.constructor);
  		  }
  		  this.services.remove(key);
  	  },
  	  
  	  start: function() {
  	     if (!this.__started) {
  		     this.modules = modules.map(function(module) {
  	    		var instance = new module(this).compose(this, 
  	    			'getUrls', 'getService', 'addService', 'removeService');
   	    		instance.load();
  	    		return instance;
  			 }, this);
  		     this.__started = true;
  		 }
  	     return this;
  	  },
  	  
  	  stop: function() {
   	     if (this.__started) {
   	    	 this.modules.forEach(function(instance) {
   	    		 try {
   	    			 instance.unload();
   	    		 } catch(err) {
   	    		 }
   			 }, this);
   	  	     this.__started = false;
   		 }
   	     delete this.modules;
   	     return this;
   	  } 	  
  });
  
//=========================================================================
// Heler class for creating urls
//=========================================================================

  var UrlHelper = base2.Base.extend({
	  constructor: function(application) {
	  	 this.application = application;
  	  },
  	  
	  forImage: function(path) {
  		  return this.application.imagePath + path;
  	  },
  	  
  	  forAjax: function(action) {
  		  var ext = action.indexOf('.') < 0 ? ".php" : "";
  		  return this.application.ajaxPath + action + ext;
  	  },
  	  
	  forAction: function(action) {
  		  return this.application.actionPath + action;
  	  }
  });

//=========================================================================
//Module class for adding behavior
//=========================================================================

  var Module = base2.Base.extend({
	  constructor: function(application) {
	  	 this.application = application;
  	  },
  	  
  	  getApplication: function() { 
  		  return this.application; 
  	  },
  	  
	  load: function() {
	  	 throw new TypeError("load method not implemented");
      },
      
	  unload: function() {}
  }, {  
	  init: function() {
	  	 var base = this.extend;
	  	 this.extend = function() {
	  		var module = base.apply(this, arguments);
	  		modules.push(module);
	  		return module;
	  	 };
  	  }
  });
  
//=========================================================================
// Class definition extensions
//=========================================================================

  function use(context, method) {
	  return bind(context[method], context);
  }
  
  Base.prototype.compose = function(context) {
	  Array2.forEach(Array2.slice(arguments, 1), function(method) {
		  this[method] = use(context, method);
	  }, this);
	  return this;
  };

//=========================================================================
// Support for ajax xmlp 
//=========================================================================

  function getCallback(callbackId) {
	  return callbacks[callbackId];
  }
  
  function registerCallback(callback, context) {
	  var callbackId = now++;
	  callbacks[callbackId] = base2.delegate(callback, context);
	  return callbackId;
  }
  
  function unregisterCallback(callbackId) {
	  return delete callbacks[callbackId];
  }

  function getCallbackQuery(callbackId) {
	  return encodeURIComponent("base2.dashfly.getCallback("+callbackId+")");
  }
  
  function parseXml(xml) {
	if (document.implementation && document.implementation.createDocument) {
		var objDOMParser = new DOMParser();
		return objDOMParser.parseFromString(xml, "text/xml");
	} else if (window.ActiveXObject) {
		var parser = new ActiveXObject('MSXML2.DOMDocument.3.0');
		parser.async = false;
		parser.loadXML(xml);
		return parser;
	}
  }
  
  eval(this.exports);
})(jQuery);


//=========================================================================
//JQuery common extensions
//=========================================================================

(function($) {
	$.fn.visible = function(visible) {
		if (visible) { this.show(); } else { this.hide(); }
	};
	  
	$.fn.appendVal = function(txt) {
		return this.each(function() {
			this.value += txt;
		});
	};
	  
	$.fn.appendText = function(txt) {
		  this.appendVal(((txt||'')+'').replace(/<\/?[^>]+(>|$)/g, "")
			 .replace(/&(nbsp|lt|gt);/g, function(match, p){
				switch(p) {
				case "nbsp": return " ";
				case "lt": return "<";
				case "gt": return ">";
				default: return pl;
				}
		 	 }));
	  };
	  
	$.fn.appendLine = function(txt) {
		  this.appendText(txt);
		  this.appendVal('\n');
	};
	  
	$.fn.centerInClient = function(options) {
		  var opt = { forceAbsolute: false,
	        container: window,
	        completed: null
		  };
		  $.extend(opt, options);

		  return this.each(function(i) {
	        var el = $(this);
	        var jWin = $(opt.container);
	        var isWin = opt.container == window;

	        // force to the top of document to ENSURE that
	        // document absolute positioning is available
	        if (opt.forceAbsolute) {
	            if (isWin) {
	                el.remove().appendTo("body");
	            }
	            else {
	                el.remove().appendTo(jWin.get(0));
	            }
	        }

	        // have to make absolute
	        el.css("position", "absolute");

	        // height is off a bit so fudge it
	        var heightFudge = 2.2;

	        var x = (isWin ? jWin.width() : jWin.outerWidth()) / 2 - el.outerWidth() / 2;
	        var y = (isWin ? jWin.height() : jWin.outerHeight()) / heightFudge - el.outerHeight() / 2;

	        el.css({ left: x + jWin.scrollLeft(), top: y + jWin.scrollTop() });

	        var zi = el.css("zIndex");
	        if (!zi || zi == "auto") {
	            el.css("zIndex", 1);
	        }

	        // if specified make callback and pass element
	        if (opt.completed) {
	            opt.completed(this);
	        }
		});
	};	
})(jQuery);

(function($) {
	var map=[];
	$.Watermark = {
		ShowAll:function(){
			for (var i=0;i<map.length;i++){
				if(map[i].obj.val()===""){
					map[i].obj.val(map[i].text);					
					map[i].obj.css("color",map[i].WatermarkColor);
				}else{
				    map[i].obj.css("color",map[i].DefaultColor);
				}
			}
		},
		HideAll:function(){
			for (var i=0;i<map.length;i++){
				if(map[i].obj.val()==map[i].text) {
					map[i].obj.val("");				
				}
			}
		}
	};
	
	$.fn.Watermark = function(text,color) {
		if(!color) {
			color="#aaa";
		}
		return this.each(
			function(){		
				var input=$(this);
				var defaultColor=input.css("color");
				map[map.length]={text:text,obj:input,DefaultColor:defaultColor,WatermarkColor:color};
				function clearMessage(){
					if(input.val()==text) {
						input.val("");
					}
					input.css("color",defaultColor);
				}

				function insertMessage(){
					if(input.val().length===0 || input.val()===text) {
						input.val(text);
						input.css("color",color);	
					} else {
						input.css("color",defaultColor);
					}
				}

				input.focus(clearMessage);
				input.blur(insertMessage);								
				input.change(insertMessage);
				
				insertMessage();
			}
		);
	};
})(jQuery);

eval(base2.dashfly.namespace);