(function($){

	/**************
	 *
	 *   function: application(context,applicationid)
	 *
	 *   Description: Gets the context and appid as the arguments constructs the baseurl and sets out a jquery object
     *	 for further chaining
	 *
	 *   return: a jquery object with baseurl and a local flag set if the context is local.
	 * ************/

	$.fn.application = function(context,applicationid) {
			if(applicationid != undefined){
				this['applicationid'] = applicationid;
			}
			else {
				logging("error","Bad parameters for the application(context,applicationid)");
                return;
			}
			if(context != '/') {
				this['baseurl'] = context +"/";
			}
			else {
				this['baseurl'] = "/";
				this['local'] = true;
			}
		return this;
	};

	/**************
	 *
	 *   function: signin(callback)
	 *
	 *   Description: Sends out a request to the server requesting for the menujson
	 *
	 *   return: jquery object with the menu data set.
	 *
	 * ************/

	$.fn.signin = function(callback) {
		local = this['local'];
		var baseurl = this['baseurl'];
		var applicationid;
		if(this['applicationid']!= undefined){
			applicationid = this['applicationid'];
		}
		baseurl = baseurl + applicationid +"/1/";
		var url = baseurl+"menu?mimetype=application/json";
		if(!local){
			url += "&callback=?";
		}
		communicate(url,false,{},function(data){
			if(data['result'] == 'OK') {
				callback({'result':'CommunicationError'});
				return;
			}
            else if (data['result'] == 'ERROR') {
                callback({'result':'DataTypeError'});
                return;
            }
			var newobj = $({});
			newobj['baseurl'] = baseurl;
			newobj['menu'] = data;
			if(local) {
				newobj['local'] = local;
			}

			callback(newobj);
		});

	};

	/**************
	 *
	 *   function: myinbox(callback)
	 *
	 *   Description: Used to get the data of myinbox.
	 *
	 *   Return: json data of the myinbox
	 * ************/

	$.fn.myinbox = function(callback) {

		if(typeof(callback) != 'function'){
			logging("error","Argument should be a callback function");
			return;
		}
		var menu = this['menu'];
		var baseurl = this['baseurl'];
		local = this['local'];
		var modelid = findModelId('User',menu);
		if (modelid == undefined) {
			logging("error","Modelid not found for the model named " + modelname);
			return;
		}
		var userdetails = getuserdetails(menu);
		var url= baseurl+modelid+'/'+userdetails['Status']+'/'+modelid+'/'+userdetails['SheetId']+"/PrimarySubscription/aggregate?dimensions=['MetadataName','MetadataId','ActivityName','ActivityDefinition']&measures=['SheetId']&operations=['count']";
		if(!local){
			url+="&callback=?";
		}
		communicate(url,false,function(data){
		callback(data);
		});
	};

	/**************
	 *
	 *   function: teaminbox(callback)
	 *
	 *   Description: Used to get the data of teaminbox.
	 *
	 *   Return: json data of the teaminbox
	 * ************/

	$.fn.teaminbox = function(callback) {
		if(typeof(callback) != 'function'){
			logging("error","Argument should be a callback function");
			return;
		}
		var menu = this['menu'];
		var baseurl = this['baseurl'];
		var local = this['local'];
		var modelid = findModelId('User',menu);
		if (modelid == undefined) {
			logging("error","Modelid not found for the model named " + modelname);
			return;
		}
		var userdetails = getuserdetails(menu);
		var url= baseurl+modelid+'/'+userdetails['Status']+'/'+modelid+'/'+userdetails['SheetId']+"/SecondarySubscription/aggregate?dimensions=['MetadataName','MetadataId','ActivityName','ActivityDefinition']&measures=['SheetId']&operations=['count']";
		if(!local){
			url+="&callback=?";
		}
		communicate(url,false,function(data){
			callback(data);
		});
	};

	/**************
	 *
	 *   function: model(modelname)
	 *
	 *   Description: Sets the model name for which the further operation chains are going to be performed.
	 *
	 *   Return: jquery object
	 *
	 * ************/

	$.fn.model = function(modelname){
		if(modelname == undefined){
			logging("error","Error while calling model(modelname), parameters missing");
			return;
		}
		var menu = this['menu'];
		var baseurl = this['baseurl'];
		var local = this['local'];
		var contextobj = new context(menu);
		if(local){
			contextobj.setLocal();
		}
		contextobj.setBaseUrl(baseurl);
		var modelid = findModelId(modelname,menu);
		if (modelid == undefined) {
			logging("error","Modelid not found for the model named " + modelname);
			return;
		}
		baseurl = baseurl + modelid + "/";
		contextobj.setBaseUrl(baseurl);
		contextobj.setModelName(modelname);
		contextobj.setModelId(modelid);
		var newobj = $({});
		newobj ['controller'] = {};
		newobj ['controller']['context'] = contextobj;
		return newobj;

	};

	/**************
	 *
	 *   function: new(data,callback)
	 *
	 *   Description: Used to create a new instance for the given model. Without the model name this function will throw an exception.
	 *
	 *   Return: jquery object
	 *
	 * ************/

	$.fn.os_new = function(data,callback) {
		if(typeof(data) == 'function' ) {
			callback = data;
			data = {};
		}
		if(callback == undefined) {
			return ({'error': 'bad parameters while calling new([data],callback)'});
		}
		var This = this;
		var context = this['controller']['context'];
		var baseurl = context.getBaseUrl();
		var modelid = context.getModelId();
		var local = context.isLocal();
		if(context == undefined || baseurl == undefined || modelid == undefined){
			logging("error","Context object is not set while trying to create a new");
			return;
		}
		var activityid = findActivityId("Start",modelid,context.getMenu());
		if(activityid == undefined) {
			logging("error","Couldn't find an activity named Start for the model " + context.getModelName());
			return;
		}
		context.setActivityId(activityid);
		baseurl = baseurl + activityid +"/"+modelid;
		context.setBaseUrl(baseurl);
		var url = baseurl + "?mimetype=application/json";
		communicate(url,local,data,"POST",function(data){
			context.setBaseUrl(context.getBaseUrl()+'/'+data['root']);
			var newobj = $(data);
			newobj['controller'] = This['controller'];
			newobj['controller']['datagraph'] = data;
			callback(newobj);
		});
	};

	/**************
	 *
	 *   function: activity(activityname)
	 *
	 *   Description: Sets the activity name for which the further operation chains are going to be performed.
	 *
	 *   Return: jquery object
	 *
	 * ************/

	$.fn.activity = function(activityname) {

		var context = this['controller']['context'];
		var menu = this['controller']['menu'];
		var baseurl,activity;
		var modelid = context.getModelId();
		if (modelid == undefined){
			logging("error","Couldn't find the model id while finding the activity id");
			return;
		}
		var activityid = findActivityId(activityname,modelid,context.getMenu());
		context.setActivityId(activityid);
		context.setActivityName(activityname);
		baseurl = context.getBaseUrl() + activityid ;
		context.setBaseUrl(baseurl);
		this['controller']['context'] =context;
		return this;

	};

	/**************
	 *
	 *   function: page(pagenumber, size, callback)
	 *
	 *   Description: fetches all the data that are in the specified model and the activity. Will throw an exception without a model and the activity.
	 *
	 *   Return: jquery object
	 *
	 * ************/

	$.fn.os_page = function(pagenumber, size, callback) {
		if($.isFunction(size)){
			callback = size;
			size = 20;
		}
		if(pagenumber==undefined || size == undefined || callback == undefined){
			logging("error","Bad Parameters for page. Page(pageNumber,[size],callback)");
			return;
		}
		var This = this;
		var context = this['controller']['context'];
		if(context == undefined) {
			logging("error","Context is undefined while trying to call a page");
			return;
		}
		if(context.getModelId() == undefined || context.getActivityId() == undefined) {
			logging("error","Model or Activity is not defined");
			callback({"error": "Model or Activity is not defined"});
			return;
		}
		var baseurl = context.getBaseUrl();
		var url = baseurl+"/p"+pagenumber+"/"+size+"?mimetype=application/json";
		if(!context.isLocal())
		{
			url+='&callback=?';
		}
		communicate(url,false,function(data){
			var root = data[data['root']];
			var instances = root['ModifiedBy.'+ context.getModelName()];
			var rows = new Array();
			for (i in instances){
				var newobj = $(data[i]);
				newobj['controller'] = This['controller'];
				newobj['referenceUrl'] = ['ModifiedBy',data[i]['SheetMetadataId'],data[i]['SheetId']];
				rows.push(newobj);
			}
			callback(rows);
		});
	};

	/**************
	 *
	 *   function: read(instanceid, callback)
	 *
	 *   Description: Reads the data for the instanceid that is being passed. The model and the activity should be defined previously before calling a read.
	 *
	 *   Return: jquery object
	 *
	 * ************/

	$.fn.read = function(instanceid,callback) {
		var This = this;
		var context = this['controller']['context'];
		var baseurl = this['controller']['baseurl'];
		if(instanceid == undefined || callback == undefined){
			logging("error","Missing Parameters for read. read(instanceid,callback(){})");
			return;
		}
		if(context.getModelId() == undefined || context.getActivityId() == undefined) {
			logging("error","Model or Activity is not defined");
			callback({"error": "Model or Activity is not defined"});
			return;
		}
		var modelid = context.getModelId();
		var url = context.getBaseUrl() +'/'+ context.getModelId()+ '/'+ instanceid ;
		context.setBaseUrl(url);
		url += '?mimetype=application/json&callback=?';
		if(!context.isLocal())
		{
			url+='&callback=?';
		}
		communicate(url,false,function(data){
			var newobj = $(data);
			this['datagraph'] = data;
			newobj['controller'] = This['controller'];
			newobj['controller']['datagraph'] = data;
			callback(newobj);

		});
	};

	/**************
	 *
	 *   function: get(referencecellname)
	 *
	 *   Description: fetches the parent from the child object
	 *
	 *   Return: jquery object
	 *
	 * ************/

	 $.fn.getInstance = function(referencecellname, referencecellid){
		var dataobj;
		var controller = this['controller'];
		var context = controller['context'];
		var datagraph = controller['datagraph'];
		if(datagraph == undefined){
			logging("error","getlist can be called only on \"read\" object. Datagraph is missing");
			return;
		}
		this.each(function(){
			dataobj = this;
		});

		var parent = dataobj[referencecellname];

		if (referencecellid == null)
			referencecellid = findCellId(referencecellname, dataobj['SheetMetadataId'], context.getMenu());

		for(sheetId in parent){
			var refUrlList = new Array();
			if(this['referenceUrl']!= undefined) {
				//copy the array
				refUrlList = this['referenceUrl'].slice();
			}
			refUrlList.push(referencecellid+'/'+controller['datagraph'][sheetId]['SheetMetadataId']+'/'+controller['datagraph'][sheetId]['SheetId']);
			var newobj = $(controller['datagraph'][sheetId]);
			newobj['controller'] = this['controller'];
			newobj['referenceUrl'] = refUrlList;
			return newobj
		}

	 }

	/**************
	 *
	 *   function: getlist(referencecellname, modelname)
	 *
	 *   Description: fetches the children for the root object
	 *
	 *   Return: jquery object
	 *
	 * ************/

	$.fn.getList = function(referencecellname,modelname, referencecellid) {
		var dataobj;
		var controller = this['controller'];
		var context = controller['context'];
		var datagraph = controller['datagraph'];
		if(datagraph == undefined){
			logging("error","getlist can be called only on \"read\" object. Datagraph is missing");
			return;
		}

		this.each(function(){
			dataobj = this;
		});
		var child = new Array();
		var children = dataobj[referencecellname+'.'+modelname];
		var modelid = dataobj['SheetMetadataId'];

		if (referencecellid == null)
			referencecellid = findRefCellId(referencecellname, modelname, modelid, context.getMenu());

		for(sheetId in children){
			var refUrlList = new Array();
			if(this['referenceUrl']!= undefined) {
				refUrlList = this['referenceUrl'].slice();
			}
			refUrlList.push(referencecellid)
			refUrlList.push(controller['datagraph'][sheetId]['SheetMetadataId'])
			refUrlList.push(controller['datagraph'][sheetId]['SheetId']);
			var newobj = $(controller['datagraph'][sheetId]);
			newobj['controller'] = this['controller'];
			newobj['referenceUrl'] = refUrlList;
			child.push(newobj);
		}
		return child;

	}

	/**************
	 *
	 *   function: getvalue(property)
	 *
	 *   Description: returns the value for the specified key in the data object
	 *
	 * ************/

	$.fn.getValue = function(cellName){
		var dataobj;
		this.each(function(){
			dataobj = this;
		});
		var currentInstance = this[0]
		var controller = this['controller'];
		var datagraph = controller['datagraph'];
		var value = dataobj[cellName]
		if (controller.pseudograph && controller.pseudograph[dataobj['SheetId']] && controller.pseudograph[dataobj['SheetId']][cellName] != null)
			value = controller.pseudograph[dataobj['SheetId']][cellName]
		if (value != null)
		{
			if (value instanceof Array)
				return value;
			else if (value instanceof Object){
				if (name.indexOf('.') == -1) {
					if(arrayContainsKey(value,'selected'))
				    {
					    return value['selected']
				    }
				    else{
						for (var key in value){
							return key
						}
					}
					return ""
				}
				return value
			}
			else{
				return value;
			}
		}
		else{
			return ""
		}
	}

	/**************
	 *
	 *   function: getdisplayvalue(property)
	 *
	 *   Description: returns the value for the specified key in the data object
	 *
	 * ************/

	$.fn.getDisplayValue = function(cellName, format, category){
		var dataobj;
		this.each(function(){
			dataobj = this;
		});
		var controller = this['controller'];
		var datagraph = controller['datagraph'];
		var value = dataobj[cellName]
		if (controller.pseudograph && controller.pseudograph[dataobj['SheetId']] && controller.pseudograph[dataobj['SheetId']][cellName] != null)
			value = controller.pseudograph[dataobj['SheetId']][cellName]
		if (value != null)
		{
			if (value instanceof Array)
				return formatdata(value, format, category)
			else if (value instanceof Object){
				if (name.indexOf('.') == -1) {
				if(arrayContainsKey(value,'selected'))
				    {
				    	sheetid = value['selected']
				    	if (sheetid && value[sheetid])
				       		return formatdata(value[sheetid], format, category)
				    }
				    else{
						for (var key in value){
							return formatdata(value[key], format, category)
						}
					}
					return formatdata("", format, category)
				}
				return formatdata(value, format, category)
			}
			else{
				return formatdata(value, format, category)
			}
		}
		else {
			return formatdata("", format, category)
		}
	}

	/**************
	 *
	 *   function: update(args)
	 *
	 *   Description: Updates the datagraph that is obtained locally.args should be in the json format
	 *
	 *   Return: jquery object
	 *
	 * ************/

	$.fn.update = function(args) {
		var This = this;
		//if it is used from generated jstl, if "this" is widget element
		if(This['controller'] == null && this.attr('data-id').length > 0){
			This = getJqueryObject(this)
			if(args == null){
				args = new Array()
			}
			args[this.attr('name')] = this.attr('value')
		}
		var context = This['controller']['context'];
		var modelid = context.getModelId();
		if(This['controller']['pseudograph']==undefined){
			This['controller']['pseudograph']= {};
		}
		this.each(function(){

			if(!This['referenceUrl']){
				var root = This['controller']['datagraph']['root'];
				This['controller']['pseudograph']['root'] = root;
				if(!This['controller']['pseudograph'][root]){
					This['controller']['pseudograph'][root]={};
				}
				for (cellName in args){
					This['controller']['pseudograph'][root][cellName] = args[cellName];
				}
			}
			else{
				var batchupdate;
				var key = This['referenceUrl'].join('/');
				if (This['referenceUrl'][0].length > 0)
					key='/'+key;
				This['controller']['pseudograph'][key]={};
				for (cellName in args){
					batchupdate = 1;
					This['controller']['pseudograph'][key][cellName] = args[cellName];
				}
				if(batchupdate!=undefined){
					This['controller']['pseudograph']['batchupdate'] = 1;
				}
			}
		});
		return This;
	};

	/**************
	 *
	 *   function: send(callback)
	 *
	 *   Description: updates the accumulated data to the server
	 *
	 *   Return: jquery object
	 *
	 * ************/

	$.fn.send = function(args, callback) {
		var This = this
		console.dir(this)
		if(typeof(args) == 'function')
			callback = args;
		else
			This = this.update(args);

		if(this['controller'] == null && this.attr('data-id').length > 0){
			var runtime_controller = $(window).attr(this.attr('data-id'));
			This = this.update()
			callback = runtime_controller.fnUpdateGraph
			alert(callback)
		}

		var context = This['controller']['context'];
		var datagraph = This['controller']['datagraph'];
		if(context == undefined || datagraph == undefined){
			logging("error","Couldnt find context or datagraph while trying to send the data");
			return;
		}
		if(This['controller']['pseudograph']==undefined){
			This['controller']['pseudograph']= {};
		}
		var updatedata = This['controller']['pseudograph'];
		if(!updatedata){
			alert("no data to update");
			return;
		}
		else{
			var url = context.getBaseUrl();
			if (url.indexOf("?")!= -1)
				url+="&"
			else
				url+="?"
			if(!This['controller']['pseudograph']['batchupdate']){
				var updatedata = updatedata[updatedata['root']];
				url+="mimetype=application/json"
				communicate(url,false,updatedata,"PUT",function(data){
					This['controller']['pseudograph']= {};
					This['controller']['datagraph'] = data;
					This[0] = data[data['root']];
					callback(This);
				});
			}
			else{
				delete This['controller']['pseudograph']['batchupdate'];
				url+="action=invoke&invoke=orangescape.model.server.services.runtime.invoke&method=batchUpdate&mimetype=application/json";
				var updatedata = JSON.stringify(This['controller']['pseudograph']);
				communicate(url,local,{'updateJson':updatedata},"POST",function(data){
					This['controller']['pseudograph']= {};
					This['controller']['datagraph'] = data;
					This[0] = data[data['root']];
					callback(This);
				});
			}
		}
	}

	/**************
	 *
	 *   function: delete(callback)
	 *
	 *   Description: Deletes the instance on which it is called. Should be called on the read object.
	 *
	 *   Return: jquery object
	 *
	 * ************/

	$.fn.osdelete = function(callback) {
		var context = this['controller']['context'];
		var url = context.getBaseUrl()+'?__method=DELETE&mimetype=application/json';
		if(!context.isLocal())
		{
			url+='&callback=?';
		}
		communicate(url,false,"DELETE",function(data){
			if(data['result'] == 'OK') {
				callback({'result':'Deleted Successfully'});
			}
			else if(data['result'] == undefined) {
					This['controller']['pseudograph']= {};
					This['controller']['datagraph'] = data;
					This[0] = data[data['root']];
					callback(This);
				}
			else {
				callback({'result':'Error while communicating the server'});
			}
		});
	};

	/**************
	 *
	 *   function: create(referencecellname,childmodel,data,callback)
	 *
	 *   Description: creates a new child record for the specified childmodel.
	 *
	 *   Return: jquery object
	 *
	 * ************/


	$.fn.create = function(referencecellname,childmodel,data,callback) {
		var This = this;
		var context = this['controller']['context'];
		var cellid = findRefCellId(referencecellname, childmodel, context.getModelId(), context.getMenu());
		var modelid = findModelId(childmodel,context.getMenu());
		var url = context.getBaseUrl() + '/' + cellid + '/' + modelid + "?__method=POST&mimetype=application/json";
		var local = context.isLocal();
		if(This['controller']['pseudograph']!= undefined){
			This.send(function(data){
				communicate(url,local,data,"POST",function(data){
					var newobj = $(data);
					newobj['controller'] = This['controller'];
					newobj['controller']['datagraph'] = $.parseJSON(data);
					callback(newobj);
				});
			});
		}
		else {
			communicate(url,local,data,"POST",function(data){
				var newobj = $(data);
				newobj['controller'] = This['controller'];
				newobj['controller']['datagraph'] = $.parseJSON(data);
				callback(newobj);
			});
		}
	}

	/**************
	 *
	 *   function: submit(name,callback)
	 *
	 *   Description: Submits the read record for the next state. name can be the caption you used for the Submit in the form.
	 *
	 *   Return: javascript object
	 *
	 * ************/

	$.fn.submit = function(name,instanceid,callback){
        var url;
		if(typeof(name) == 'function') {
			callback = name;
			name = 'Submit';
            instanceid=undefined;
		}
        if(typeof(instanceid) == 'function') {
            callback = instanceid;
            instanceid = undefined;
        }
		if(callback == undefined) {
			logging("error","submit should be passed a callback");
			return;
		}
		var This = this;
		var context  = this['controller']['context'];
		if(context == undefined){
			logging("error","Context is undefined while trying to invoke the action Submit");
			return;
		}
        if(instanceid == undefined) {
            url = context.getBaseUrl()+"?action=invoke&invoke=" + name;
        }
        else {
            url = context.getBaseUrl() + '/' + context.getModelId() + '/' + instanceid + "?action=invoke&invoke=" + name;
        }
		var local = context.isLocal();
		if(This['controller']['pseudograph']!= undefined){
			communicate(url,local,"POST",function(data){
				if(data['result'] == 'OK') {
					callback({'result':'Submitted Successfully'});
				}
				else if(data['result'] == undefined) {
					This['controller']['pseudograph']= {};
					This['controller']['datagraph'] = data;
					This[0] = data[data['root']];
					callback(This);
				}
				else {
					callback({'result':'Error while communicating the server'});
				}
			});
		}
		else{
			communicate(url,local,"POST",function(data){
				if(data['result'] == 'OK') {
					callback({'result':'Submitted Successfully'});
				}
				else if(data['result'] == undefined) {
					This['controller']['pseudograph']= {};
					This['controller']['datagraph'] = data;
					This[0] = data[data['root']];
					callback(This);
				}
				else {
					callback({'result':'Error while communicating the server'});
				}
			});
		}
	}

	/**************
	 *
	 *   function: invoke(actionname, callback)
	 *
	 *   Description: calls the action in the specified actionname
	 *
	 *   Return: javascript object
	 *
	 * ************/

	$.fn.invoke = function(actionname,callback){
		if (actionname == undefined || callback == undefined){
			logging("error","Missing parameters for invoke(actionname, callback");
			return;
		}
		var context  = this['controller']['context'];
		if(context == undefined){
			logging("error","Context is undefined while trying to invoke the action "+ actionname);
			return;
		}
		var This = this;
		var url = context.getBaseUrl()+"?action=invoke&invoke=" + actionname;
		var local = context.isLocal();
		if(This['controller']['pseudograph']!= undefined){
			communicate(url,local,"POST",function(data){
				if(data['result'] == 'OK') {
					callback({'result':'Invoked Successfully'});
				}
				else if(data['result'] == undefined) {
					This['controller']['pseudograph']= {};
					This['controller']['datagraph'] = data;
					This[0] = data[data['root']];
					callback(This);
				}
				else {
					callback({'result':'Error while communicating the server'});
				}
			});
		}
		else{
			communicate(url,local,"POST",function(data){
				if(data['result'] == 'OK') {
					callback({'result':'Invoked Successfully'});
				}
				else if(data['result'] == undefined) {
					This['controller']['pseudograph']= {};
					This['controller']['datagraph'] = data;
					This[0] = data[data['root']];
					callback(This);
				}
				else {
					callback({'result':'Error while communicating the server'});
				}
			});
		}
	}

	/**************
	 *
	 *   function: search(cellname, callback)
	 *
	 *   Description: searched for the values for the specified cellname
	 *
	 *   Return: javascript object
	 *
	 * ************/

	$.fn.search = function(cellname,data,callback) {
        var urldata = {};
        if(typeof(data) == 'function'){
            callback = data;
            data = undefined;
        }
        if(data != undefined ) {
            for( i in data) {
                urldata['$'+i] = data[i];
            }
        }
		var context = this['controller']['context'];
		var baseurl = context.getBaseUrl();
		var url = baseurl + '/' +cellname+ '/search?mimetype=application/json';
		communicate(url,false,urldata,function(data){
			var json = data[data['root']];
			for(i in json) {
				data = json[i];
			}
			callback(data);
		});
	}


     /**************
	 *
	 *   function: aggregate
	 *
	 *   Description : calls the aggregate api
	 *
	 *  return: Javascript object
	 *
	 * ************/
     $.fn.aggregate = function(dimensions,measures,operations,callback) {
        alert("Coming inside aggregate");
        var controller = this['controller'];
		var context = controller['context'];
        var url = context.getBaseUrl()+"/aggregate?dimensions=['"+ dimensions.join('\',\'')+"']&measures=['"+ measures.join('\',\'')+"']&operations=['"+ operations.join('\',\'')+"']&callback=?";
        communicate(url,false,function(data){
                callback(data);
		});

     }

    /**************
	 *
	 *   function: query
	 *
	 *   Description: queries with the given conditions
	 *
	 *   Return : Javascript object
	 *
	 * ************/
     $.fn.query = function(referencecell,callback) {
        alert("Coming inside query");
        var controller = this['controller'];
		var context = controller['context'];
        var url = context.getBaseUrl() + '/' +referencecell+ '/query?mimetype=application/json';
        logging("error",url);
        communicate(url,false,function(data){
			callback(data);
		});

     }
     /**************
	 *
	 *   function: advancedsearch(cellname, callback)
	 *
	 *   Description: searched for the values for the specified cellname
	 *
	 *   Return: javascript object
	 *
	 * ************/

	$.fn.advancedsearch = function(cellname,data,callback) {
        var urldata = {};
        if(typeof(data) == 'function'){
            callback = data;
            data = undefined;
        }
        if(data != undefined ) {
            for( i in data) {
                urldata['$'+i] = data[i];
            }
        }
		var context = this['controller']['context'];
		var baseurl = context.getBaseUrl();
		var url = baseurl + '/' +cellname+ '/search?mimetype=application/json';
		communicate(url,false,urldata,function(data){
			callback(data);
		});
	}

    $.fn.instance = function(instanceid){
        var This = this;
		var context = this['controller']['context'];
		var baseurl = this['controller']['baseurl'];
        var url = context.getBaseUrl() +'/'+ context.getModelId()+ '/'+ instanceid ;
        context.setBaseUrl(url);
        return this;
    }

	$.fn.getmenujson = function(host,applicationid,callback) {
		if(host == undefined || applicationid == undefined) {
			return ({'error': 'bad parameters'});
		}
		var url = host+'/'+applicationid+'/1/'+"menu?mimetype=application/json&callback=?";
		communicate(url,false,function(data){
			callback(data);
		});
	}

})(jQuery);

function communicate(url,local,data,method,callback){
	$.ajaxSetup({
		error: function(response,error) {
			if (response.status == 200 ) {
				callback({'result':'OK'});
			}
		}
	});
	if(typeof(data) == 'function') {
		callback = data;
		data = {};
		method = "GET";
	}
	else if(typeof(method) == 'function' && typeof(data) == 'object') {
		callback = method;
		method = 'GET';
	}
	else if(typeof(method) == 'function' && typeof(data) == 'string') {
		callback = method;
		method = data;
		data = {};
	}

	if(!local){
		url+="&__method="+method+"&callback=?";
		$.getJSON(url,data,function(returndata){
			callback(returndata);
		});
	}
	else{
		$.ajax({
			type: method,
			url: url,
			dataType: 'json',
			data: data,
			success: function(returndata){
				callback(returndata);
			}
		});
	}

}