appdb.ModelItemClass = function(opts,ext){
    opts = opts || {};
    ext = ext || {};
    ext.async = ((typeof ext.async === 'boolean'?ext.async:true));
    var _mediator = new appdb.utils.ObserverMediator(), _getCaller = null, _insertCaller = null, _removeCaller = null,_updateCaller = null, _modelProperty= null, _localData = null;
	var _getsuccess = function(d){
		if(d.error){
			_geterror(d);
		}
        if(typeof _modelProperty === "string"){
            d = d[_modelProperty];
        }
		_localData = d;
        _mediator.publish({event : 'select',value : d});
    };
	var _insertsuccess = function(d){
		if(d.error){
			_geterror(d);
		}
		if(typeof _modelProperty === "string"){
            d = d[_modelProperty];
        }
        _mediator.publish({event : 'insert',value : d});
	};
	var _removesuccess = function(d){
		if(d.error){
			_geterror(d);
		}
		if(typeof _modelProperty === "string"){
            d = d[_modelProperty];
        }
        _mediator.publish({event : 'remove',value : d});
	};
	var _updatesuccess = function(d){
		if(d.error){
			_geterror(d);
		}
		if(typeof _modelProperty === "string"){
            d = d[_modelProperty];
        }
        _mediator.publish({event : 'update',value : d});
	};
    var _geterror = function(d){
        _mediator.publish({event : 'error',value : d});
    };
    var _get = function(d){
        var p;
        if(typeof d !== "undefined"){
            if($.isPlainObject(d)){
                p = {query : d};
            }
        }
        _mediator.publish({event:"beforeselect",value : p});
        return _getCaller.call(p);
    };
	var _remove = function(d){
		var p;
		if(typeof d !== "undefined"){
            if($.isPlainObject(d)){
                p = {query : d};
            }
        }
        _mediator.publish({event:"beforeremove",value : p});
        return _removeCaller.call(p);
	};
	var _insert = function(d){
		var p;
		if(typeof d !== "undefined"){
            if($.isPlainObject(d)){
                p = {query : d};
            }
        }
        _mediator.publish({event:"beforeinsert",value : p});
        return _insertCaller.call(p);
	};
	var _update = function(d){
		var p;
		if(typeof d !== "undefined"){
            if($.isPlainObject(d)){
                p = {query : d};
            }
        }
        _mediator.publish({event:"beforeupdate",value : p});
        return _updateCaller.call(p);
	}
    var _subscribe = function(s){
        _mediator.subscribe(s);
        return this;
    };
    var _unsubscribe = function(s){
         _mediator.unsubscribe(s);
         return this;
    };
    var _unsubscribeAll = function(c){
        _mediator.unsubscribeAll(c);
         return this;
    };
    var _getQuery = function(){
        return _getCaller.getQuery();
    };
    var _getData = function(){
        return _getCaller.getData();
    };
	var _getLocalData = function(){
		return _localData;
	};
    var _destroy = function(){
        _mediator.clearAll();
    };
    var _init = function(){
        var cl = {
            success : _getsuccess,
            error : _geterror
        }
        ext.caller = $.extend(cl,ext.caller);
        _modelProperty = (ext.modelProperty && (typeof ext.modelProperty === "string"))?ext.modelProperty:null;
        _getCaller = new appdb.utils.rest(ext.caller);
        if(ext.async===false){
            _getCaller = _getCaller.create({query:opts});
        }else{
            _getCaller = _getCaller.create({query:opts},{success : _getsuccess,error : _geterror});
        }

		if(ext.insertCaller){
			_insertCaller = new appdb.utils.rest(ext.insertCaller);
			if(ext.async===false){
				_insertCaller = _insertCaller.create({query:opts});
			}else{
				_insertCaller = _insertCaller.create({query:opts},{success : _insertsuccess,error : _geterror});
			}
		}else{
			_insertCaller = function(){};
		}
		if(ext.removeCaller){
			_removeCaller = new appdb.utils.rest(ext.removeCaller);
			if(ext.async===false){
				_removeCaller = _removeCaller.create({query:opts});
			}else{
				_removeCaller = _removeCaller.create({query:opts},{success : _removesuccess,error : _geterror});
			}
		}else{
			_removeCaller = function(){};
		}
		if(ext.updateCaller){
			_updateCaller = new appdb.utils.rest(ext.updateCaller);
			if(ext.async===false){
				_updateCaller = _updateCaller.create({query:opts});
			}else{
				_updateCaller = _updateCaller.create({query:opts},{success : _updatesuccess,error : _geterror});
			}
		}else{
			_updateCaller = function(){};
		}
    };
    _init();
    return {
        get : _get,
		remove : _remove,
		insert : _insert,
		update : _update,
        getQuery : _getQuery,
        getData : _getData,
		getLocalData : _getLocalData,
        subscribe : _subscribe,
        unsubscribe : _unsubscribe,
        unsubscribeAll : _unsubscribeAll,
        destroy : _destroy
    };
};
appdb.ModelListClass = function(opts,ext){
    opts = opts || {};
    ext = ext || {};
    ext.async = ((typeof ext.async ==='boolean')?ext.async:true);
    var _mediator = new appdb.utils.ObserverMediator(this), _getCaller = null, _pager = null , _localData = null;

    var _getsuccess = function(d){
		_localData = d;
        _mediator.publish({event : 'select',value : d});
    };
    var _geterror = function(d){
        _mediator.publish({event : 'error',value : d});
    };
    this.get = function(d){
        var p;
        if(typeof d !== "undefined"){
            if($.isPlainObject(d)){
                p = {query : d};
            }
        }
        _mediator.publish({event:"beforeselect",value : p});
        var res = _getCaller.call(p);
        return res;
    };
    this.subscribe = function(s){
        _mediator.subscribe(s);
        return this;
    };
    this.unsubscribe = function(s){
         _mediator.unsubscribe(s);
         return this;
    };
    this.unsubscribeAll = function(clr){
        _mediator.unsubscribeAll(clr);
         return this;
    };
    this.getPager = function(){
        if(_pager===null){
            var pageopt = {};
            if(opts.pagelength){
                pageopt["length"] = opts.pagelength || ext.pagelength;
            }
            if(opts.pageoffset){
                pageopt["offset"] = opts.pageoffset;
            }
            pageopt["model"] = this;
            pageopt["modelProperty"] = ext.modelProperty;
            _pager = new appdb.utils.Pager(pageopt);
        }
        return _pager;
    };
    this.getQuery = function(){
        return _getCaller.getQuery();
    };
    this.getData = function(){
        return _getCaller.getData();
    };
	this.getLocalData = function(){
		return _localData;
	};
    this.destroy = function(){
        _mediator.clearAll();
    };
    var _init = function(){
        var cl = {
            success : _getsuccess,
            error : _geterror
        }
       // _usecache = (ext.cache)?true:false;
        if(typeof ext.caller === "undefined" && ext.localData){
             _getCaller = new appdb.utils.LocalDataStore({localData : ext.localData});
        }else{
            ext.caller = $.extend(cl,ext.caller);
             _getCaller = new appdb.utils.rest(ext.caller);
        }
        if(ext.async===false){
            _getCaller = _getCaller.create({query:opts});
        }else{
            _getCaller = _getCaller.create({query:opts},{success : _getsuccess,error : _geterror});
        }
    };
    _init();
    this.Obs = _mediator;
};
appdb.model = {};
appdb.model.Person = function(opts,ext){
    var _init  = function(){
        opts = opts || {};
        ext = ext || {};
        ext.caller = {
            endpoint : appdb.config.endpoint.baseapi + "people/{id}/?{*}",
			authorization : {
			   type : appdb.utils.rest.authorization.types.query,
			   mode : appdb.utils.rest.authorization.modes.authonly
		   }
        };
        ext.modelProperty = "person";
        return new appdb.ModelItemClass(opts, ext);
    };
    return _init();
};
appdb.model.People = function(opts,ext){
    var _init = function(){
        opts = opts || {};
        ext = ext || {};
        ext.caller = {
            endpoint : appdb.config.endpoint.baseapi + "people?{*}",
			authorization : {
			   type : appdb.utils.rest.authorization.types.query,
			   mode : appdb.utils.rest.authorization.modes.authonly
			}
        };
        ext.modelProperty = "person"
        return new appdb.ModelListClass(opts,ext);
    };
    return _init();
};
appdb.model.PeopleApplications = function(opts,ext){
    var _init = function(){
        opts = opts || {};
        ext = ext || {};
        ext.caller = {
            endpoint : appdb.config.endpoint.baseapi + "people/{id}/applications/{applicationtype}?{*}",
			authorization : {
			   type : appdb.utils.rest.authorization.types.query,
			   mode : appdb.utils.rest.authorization.modes.authonly
			}
        };
        ext.modelProperty = "application"
        return new appdb.ModelListClass(opts,ext);
    };
    return _init();
};
appdb.model.Applications = function(opts,ext){
    var _init = function(){
        opts = opts || {};
        ext = ext || {};
		var subtype = "";
		if ( opts.applicationtype ) {
			if ( opts.applicationtype == "moderated" ) {
				subtype = "/moderated";
				delete opts.applicationtype;
			} else if ( opts.applicationtype == "deleted" ) {
				subtype = "/deleted";
				delete opts.applicationtype;
			}
		}
        ext.caller = {
            endpoint : appdb.config.endpoint.baseapi + "applications"+subtype+"?{*}",
			authorization : {
				   type : appdb.utils.rest.authorization.types.query,
				   mode : appdb.utils.rest.authorization.modes.authonly
			}
		};
        ext.modelProperty = "application";
        return new appdb.ModelListClass(opts, ext);
    };
    return _init();
};
appdb.model.RelatedApplications = function(opts,ext){
    var _init = function(){
        opts = opts || {};
        ext = ext || {};
		var subtype = "";
        ext.caller = {
            endpoint : appdb.config.endpoint.baseapi + "applications/{appid}/relatedapps"+"?{*}",
			authorization : {
				   type : appdb.utils.rest.authorization.types.query,
				   mode : appdb.utils.rest.authorization.modes.authonly
			}
		};
        ext.modelProperty = "relatedapp.application";
        return new appdb.ModelListClass(opts, ext);
    };
    return _init();
};
appdb.model.Genders = {
        get : function(){
            return [{key : "male", name : "Male"},
                {key : "female", name : "Female"},
                {key : "", name : "N\\A"}];
        }
    };
appdb.model.Disciplines = (function(opts,ext){
	return new function(){
		opts = opts || {};
		ext = ext || {};
		ext.caller = {
			endpoint : appdb.config.endpoint.baseapi + "disciplines",
			authorization : {
			   type : appdb.utils.rest.authorization.types.query,
			   mode : appdb.utils.rest.authorization.modes.authonly
			}
		};
		var res = new appdb.ModelListClass(opts,ext);
		res.get();
		return res;
	};
})();
appdb.model.Middlewares = (function(opts,ext){
	return new function(){
		opts = opts || {};
		ext = ext || {};
		ext.caller = {
			endpoint : appdb.config.endpoint.baseapi + "middlewares",
			authorization : {
			   type : appdb.utils.rest.authorization.types.query,
			   mode : appdb.utils.rest.authorization.modes.authonly
			}
		};
		var res = new appdb.ModelListClass(opts,ext);
		res.get();
		return res;
	};
})();
appdb.model.Regional = (function(){
    var  opts = {}, ext = {},local,_countries = [],_regions=[],_providers=[],
    _getCountries = function(){
        return _countries;
    },
    _getRegions = function(){
        return _regions;
    },
    _getProviders = function(){
        return _providers;
    },
    _instance = {Countries : {get : _getCountries}, Regions : {get : _getRegions}, Providers: {get : _getProviders}},
    _error = function(d){
        console.log("[appdb.model.Regional]:Could not load regional data:"+d.description,d);
        local.destroy();
        local = null;
    },
    _success=function(d){
            if(d.country){
                if($.isArray(d.country)===false){
                    d.country = [d.country];
                }
                _countries = d.country;
            }
            if(d.region){
                if($.isArray(d.region)===false){
                    d.region = [d.region];
                }
                _regions = d.region;
            }
            if(d.provider){
                if($.isArray(d.provider)){
                    d.provider = [d.provider];
                }
                _providers = d.provider;
            }
            local.destroy();
            local = null;
    };

    ext.caller = {
        endpoint : appdb.config.endpoint.baseapi + "regional",
		authorization : {
			   type : appdb.utils.rest.authorization.types.query,
			   mode : appdb.utils.rest.authorization.modes.authonly
			}
    };
    local = new appdb.ModelListClass(opts, ext);
    local.subscribe({event:'select',callback: _success});
    local.subscribe({event:'error',callback:_error});
    local.get();
    return _instance;
})();
appdb.model.Roles = (function(){
    var _roles=[],local,
    _getRoles = function(){
        return _roles;
    },_instance ={get : _getRoles},
    ext = {caller : {
			endpoint : appdb.config.endpoint.baseapi + "roles",
			authorization : {
			   type : appdb.utils.rest.authorization.types.query,
			   mode : appdb.utils.rest.authorization.modes.authonly
			}}};
    var _success = function(d){
        _roles = d.role;
        if($.isArray(_roles)===false){
            _roles = [_roles];
        }
        local.destroy();
        local=null;
    };
    var _error = function(d){
        console.log("[appdb.model.Roles]:Could not load roles data:"+d.description,d);
        local.destroy();
        local = null;
    };
    local = new appdb.ModelListClass({}, ext);
    local.subscribe({event:'select',callback:_success});
    local.subscribe({event:'error',callback:_error});
    local.get();
    return _instance;
})();
appdb.model.ContactTypes = (function(){
    var _ctypes =[],local,
    _getCTypes = function(){
        return _ctypes;
    },_instance = {get : _getCTypes},
    ext = {caller:{endpoint:appdb.config.endpoint.baseapi+"contacttypes"}},
    _success = function(d){
        _ctypes = d.contact;
        if($.isArray(_ctypes)===false){
            _ctypes = [_ctypes];
        }
        local.destroy();
        local = null;
    },
    _error = function(d){
        console.log("[appdb.model.ContactTypes]:Could not load contact types:"+d.description,d);
        local.destroy();
        local = null;
    };
    local = new appdb.ModelListClass({}, ext);
    local.subscribe({event:'select',callback:_success});
    local.subscribe({event:'error',callback:_error});
    local.get();
    return _instance;
})();
appdb.model.VOs = function(opts,ext){
  var _init = function(){
        opts = opts || {};
        ext = ext || {};
        ext.caller = {
            endpoint : appdb.config.endpoint.baseapi + "vos?{*}",
			authorization : {
			   type : appdb.utils.rest.authorization.types.query,
			   mode : appdb.utils.rest.authorization.modes.authonly
			}
        };
        ext.modelProperty = "vo"
        return new appdb.ModelListClass(opts,ext);
    };
    return _init();
};
appdb.model.ApplicationRatings = function(opts,ext){
    var _init = function(){
        opts = opts || {};
        ext = ext || {};
        ext.caller = {
            endpoint : appdb.config.endpoint.baseapi + "applications/{id}/ratings",
			authorization : {
			   type : appdb.utils.rest.authorization.types.query,
			   mode : appdb.utils.rest.authorization.modes.authonly
			}
        };
        ext.modelProperty = "rating"
        return new appdb.ModelListClass(opts,ext);
    };
    return _init();
};
appdb.model.RatingReport = function(opts,ext){
    var _init = function(){
        opts = opts || {};
        ext = ext || {};
        ext.caller = {
            endpoint : appdb.config.endpoint.baseapi + "applications/{appid}/ratingsreport/{type}",
			authorization : {
			   type : appdb.utils.rest.authorization.types.query,
			   mode : appdb.utils.rest.authorization.modes.authonly
			}
        };
        ext.modelProperty = "ratingreport"
        return new appdb.ModelListClass(opts,ext);
    };
    return _init();
};
appdb.model.Tags = (function(opts,ext){
	return new function(){
		opts = opts || {};
		ext = ext || {};
		ext.caller = {
			endpoint : appdb.config.endpoint.baseapi + "tags",
			authorization : {
			   type : appdb.utils.rest.authorization.types.query,
			   mode : appdb.utils.rest.authorization.modes.authonly
			}
		};
		var res = new appdb.ModelListClass(opts,ext);
		res.get();
		return res;
	};
})();
appdb.model.ApplicationTags = function(opts,ext){
	var _init = function(){
        opts = opts || {};
        ext = ext || {};
        ext.caller = {
            endpoint : appdb.config.endpoint.base + "apps/tags?id={id}"
        };
        ext.removeCaller = {
                endpoint : appdb.config.endpoint.base + "apps/tags?id={id}&tag={tag}&action=remove"
        };
        ext.insertCaller = {
                endpoint : appdb.config.endpoint.base + "apps/tags?id={id}&tag={tag}&action=add"
        };
        return new appdb.ModelItemClass(opts,ext);
    };
    return _init();
};
appdb.model.ApplicationTagPolicy = function(opts,ext){
	var _init = function(){
        opts = opts || {};
        ext = ext || {};
        ext.caller = {
            endpoint : appdb.config.endpoint.base + "apps/tagpolicy?id={id}"
        };
        ext.insertCaller = {
                endpoint : appdb.config.endpoint.base + "apps/tagpolicy?id={id}&p={policy}"
        };
        return new appdb.ModelItemClass(opts,ext);
    };
    return _init();
};
appdb.model.MailSubscription = function(opts,ext){
	var _init = function(){
		opts = opts || {};
		ext = ext || {};
		ext.caller = {
			endpoint : appdb.config.endpoint.base + "news/getsubscription?flt={flt}"
		};
		ext.insertCaller = {
			endpoint : appdb.config.endpoint.base + "news/subscribe?flt={flt}&name={name}&subjecttype={subjecttype}&events={events}&delivery={delivery}"
		};
		ext.removeCaller = {
			endpoint : appdb.config.endpoint.base + "news/unsubscribe?id={id}&pwd={pwd}&src=ui"
		};
		ext.updateCaller = {
			endpoint : appdb.config.endpoint.base + "news/subscribe?id={id}&flt={flt}&name={name}&subjecttype={subjecttype}&events={events}&delivery={delivery}"
		};
		return new appdb.ModelItemClass(opts,ext);
	};
	return _init();
};
appdb.model.RoleMailSubscription = function(opts,ext){
	var _init = function(){
		opts = opts || {};
		ext = ext || {};
		ext.caller = {
			endpoint : appdb.config.endpoint.base + "news/getrolesubscription"
		};
		ext.insertCaller = {
			endpoint : appdb.config.endpoint.base + "news/subscribe?flt={flt}&name={name}&subjecttype=ppl&events=96&delivery=1"
		};
		ext.removeCaller = {
			endpoint : appdb.config.endpoint.base + "news/unsubscribe?id={id}&pwd={pwd}&src=ui"
		};
		return new appdb.ModelItemClass(opts,ext);
	};
	return _init();
};
appdb.model.MailSubscription.defaultNotification = null;
appdb.model.MailSubscription.roleNotification = null;

appdb.model.PrimaryContact = function(opts,ext){
    var _init = function(){
        opts = opts || {};
        ext = ext || {};
        ext.updateCaller = {
            endpoint : appdb.config.endpoint.base + "people/primarycontact?act=set&id={id}"
        };
        ext.caller = {
            endpoint : appdb.config.endpoint.base + "people/primarycontact?act=get"
        }
        return new appdb.ModelItemClass(opts,ext);
    };
    return _init();
};
appdb.model.PrimaryContact.userPrimaryContact = null;
appdb.model.PrimaryContact.userPrimaryContactId = null;

appdb.model.NameAvailability = function(opts,ext){
	var _init = function(){
		opts = opts || {};
		ext = ext || {};
		ext.caller = {
			endpoint : appdb.config.endpoint.base + "apps/nameavailable?n={name}"
		};
		return new appdb.ModelItemClass(opts,ext);
	};
	return _init();
};

appdb.model.UsedAppUrlTitles = (function(opts,ext){
 var _init = function(){
  opt = opts || {};
  ext = ext || {};
  ext.caller = {
   endpoint : appdb.config.endpoint.base + "apps/usedurltitles"
  };
  return new appdb.ModelItemClass(opts, ext);
 };

 var res = _init();
 res.get();
 return res;
})();
