var G_IS_OPENSOCIAL = true;
var GALLERY_SERVER_URL = "http://justlocate.com/gallery/";
var GALLERY_PROXY_URL = "http://gt.doflirt.com/facebook/game/puzzle_gallery/simple_proxy.php";
var GALLERY_USE_PROXY = false;
var G_IS_LIVE = true;

function Gallery(user, columns, limit, 
		pSourceApp, tag_name_list, 
		tag_cloud_position, afterSaveCallBack, click_CallBack, 
		social_type, item_type, pCategory){

	var self = this;
	
	var PAGE_LIMIT = 9;
	var COL_COUNT = 3;
	var PAGING_RANGE=3;
	var IMAGE_MAX_WIDTH = 400;
	var IMAGE_MAX_HEIGHT = 400;
	
	this.constructor.UNPUBLISHED_KEY = 0;
	this.constructor.PUBLISHED_KEY = 1;
	this.constructor.PUBLISHED_AND_UNPUBLISHED_KEY = 2;
	this.context = {};
	
	var tempKey = "";
	
	var galleryUserId;
	var galleryUserName;
	var galleryUserThumbnail;
	var galleryUserProfile;
	
	var sourceApp="";
	var socialType = "myspace";//can be myspace,friendster,hi5,orkut,facebook or even combined with coma
	this.itemTypes = {"IMG":"images", "TEXT":"text", "DOC":"docs", "MUSIC":"musics", "VIDEO":"videos", "AUTODETECT":"items"};
	var itemType = "IMG";
	
	var category = "all";//will bring all groups without filtering
	
	var galleryAllContent="";
	var afterSaveCallBackGlob = "";
	var clickCallBack = "";
	
	
	var sortOrders={"newest":"Newest", "dailypopular":"Daily Popular", "weeklypopular":"Weekly Popular", "popular":"Most Popular"};
	
	var allTagsForImages = [];
	var tagNameList = "";
	var tagCloudPosition = "top";
	
	var currentPage = 0;
	var currentTag = 0;
	var currentSort = "newest";
	var currentPublished = self.UNPUBLISHED_KEY;
	

	//properties
	this.generateUploadToken = function(){
		tempKey = galleryUserId+"_"+new Date().getTime();
		return tempKey;
	}
	
	this.getUploadToken = function(){
		return tempKey;
	}

	this.getUserId = function(){
		return galleryUserId;
	}
	
	this.getUploadUrlForFlash = function(){
		return GALLERY_SERVER_URL + "images/upload-step1-flash";
	}
	
	this.getUploadUrlForFlashInOneStep = function(pPublished, pSocialType, pItemType, pCategory, pDescription, pProperty1){
		pPublished = typeof pPublished=='undefined' || pPublished==null  ? (typeof currentPublished=='undefined' ? Gallery.UNPUBLISHED_KEY : currentPublished) : pPublished;
		pSocialType = typeof pSocialType == 'undefined' || pSocialType==null ? socialType : pSocialType;
		pItemType = typeof pItemType == 'undefined' || pItemType==null ? itemType : pItemType;  
		category = typeof pCategory == 'undefined' || pCategory==null ? category : pCategory; 
		pDescription = typeof pDescription == 'undefined' || pDescription==null ? '' : pDescription;
		pProperty1 = typeof pProperty1 == 'undefined' || pProperty1==null ? '' : pProperty1;
		
			var data = "model.user.socialId="+galleryUserId+
						"&model.user.socialName="+galleryUserName+
						"&model.user.socialType="+pSocialType+
						"&model.user.socialProfileUrl="+encodeURIComponent(galleryUserProfile)+
						"&model.user.socialThumbUrl="+encodeURIComponent(galleryUserThumbnail)+
						"&model.status="+pPublished+
						"&model.itemType="+pItemType+
						"&model.category="+category+
						"&model.source="+sourceApp+
						"&model.description="+pDescription+
						"&model.property1="+pProperty1;
		return GALLERY_SERVER_URL + "images/upload-flash?"+encodeURIComponent(data);
	}
	
	this.getUploadUrl = function(){
		return GALLERY_SERVER_URL+'images/upload-step1-simple/form?uploadToken='+self.generateUploadToken()+'&imgDisplayWidth='+IMAGE_MAX_WIDTH+'&t='+new Date().getTime();
	}
	this.getImageMaxWidth = function(){
		return IMAGE_MAX_WIDTH;
	}
	this.getImageUrlRoot = function(){
		return GALLERY_SERVER_URL+'images';
	}

	this.getSortOrder = function(){
		return currentSort;
	}
	this.setSortOrder = function(sorting){
		currentSort = sorting;
	}

	this.getPublished = function(){
		return currentPublished;
	}
	this.setPublished = function(published){
		currentPublished = published;
	}
	
	this.getSupportedSortOrders = function(){
		return sortOrders;
	}
	
	this.setSortOrders = function(sO){
		sortOrders = sO;
	}
	
	this.switchCategory = function(cat){
		category = cat;
		self.context["category"] = cat;
	}
	
	this.setItemType = function(pItemType){
		itemType = pItemType;
		self.context["itemType"] = pItemType;
	}
	
	//~properties
	
	//server calls
	/**
	 * call directly to server, response from server will be directed to provided callback
	 *  
	 * pPage - page number if not provided first page will be used
	 * pPublished - 0 mean private item private to user, 1 mean public gallery items, if not provided private items will be served
	 * pCallbackGetItems - callback method to which return response
	 * pSocialId - social id of user if not provided current user social id will be used, if provided 'all' then will return for all users
	 * pSocialType
	 * pItemType
	 * pCategory
	 * pIncludeUserCategories - if true categories will be returned in json response
	 * pFetchItemSharings - if true include shared with user's info in the result json
	 * pFilterBySharedWith - if true will bring items that are shared with pSocialId an pSocialType properties
	 */
	this.getItems = function(pPage, pPublished, pCallbackGetItems, 
			pSocialId, pSocialType, pItemType, pCategory, 
			pIncludeUserCategories, pFetchItemSharings, pFilterBySharedWith){
		//force to switch current page
		currentPage = typeof pPage == 'undefined' || pPage==null ? 0 : pPage;
		currentPublished = typeof pPublished=='undefined' || pPublished==null ? currentPublished : pPublished;
		this.context["socialId"] = typeof pSocialId == 'undefined' || pSocialId==null ? this.context["socialId"] : pSocialId;
		pSocialType = typeof pSocialType == 'undefined' || pSocialType==null ? socialType : pSocialType;
		pItemType = typeof pItemType == 'undefined' || pItemType==null ? itemType : pItemType;
		//force to switch current category
		category = typeof pCategory == 'undefined' || pCategory==null ? category : pCategory; 
		pIncludeUserCategories = typeof pIncludeUserCategories == 'undefined' || pIncludeUserCategories==null ? false : true; 
		pFetchItemSharings = typeof pFetchItemSharings == 'undefined' || pFetchItemSharings==null ? false : true;
		pFilterBySharedWith = typeof pFilterBySharedWith == 'undefined' || pFilterBySharedWith==null ? false : true;
		
	    GalleryRequest.sendGET(GALLERY_SERVER_URL + "images?published=" + currentPublished + 
	    		"&page=" + currentPage + "&limit=" + PAGE_LIMIT+
	    		(typeof currentTag!='undefined' && currentTag!=0 ? "&tagStringList="+currentTag : "")+
	    		"&sortOrder="+currentSort+
	    		"&socialId="+this.context["socialId"]+
	    		"&socialType="+pSocialType+
	    		"&itemType="+pItemType+
	    		"&category="+category+
	    		"&source="+sourceApp+
	    		"&includeUserCategories="+pIncludeUserCategories+
	    		"&fetchItemSharings="+pFetchItemSharings+
	    		"&filterBySharedWith="+pFilterBySharedWith+
                "&time="+getCurrentTime(), 
	    		pCallbackGetItems, socialType);
	}
	
	/**
	 * returns tags in callback
	 */
	this.getTags = function(callback_getTags){
		GalleryRequest.sendGET(GALLERY_SERVER_URL + "gallery/tag?"+(tagNameList != "" ? "tagNameList="+tagNameList : "")+"&page=0&limit=30&source="+sourceApp, callback_getTags, socialType);
	}
	
	/**
	 * allows user to vote for item, a user can vote only once for item
	 * itemId - unique Id of item, as far as it is unique and only auth user can vote no other parameters required
	 * callback_addVote - name of callback method where response will return
	 * voteValue - can be 1 to 5 if not provided 1
	 */
	this.vote = function(itemId, callback_addVote, pVoteValue){
		voteValue = typeof pVoteValue == 'undefined' || pVoteValue==null ? 1 : pVoteValue;
	    var data = "socialId=" + galleryUserId + "&socialType="+ socialType +"&voteValue=" +voteValue;
	    GalleryRequest.sendPOST(GALLERY_SERVER_URL + "images/"+itemId+"/vote", data, callback_addVote, socialType);
	}
	 
	 /**
	 * allows user to add comment for item
	 * pItemId - unique Id of item
	 * pCallback_addComment - name of callback method where response will return
	 * pComment - should be script free html
	 */
	this.comment = function(pItemId, pCallback_addComment, pComment){
	    var data = 
	    	//"comment.itemId=" + pItemId +
	    "comment.user.socialId="+galleryUserId + 
	    "&comment.body="+ pComment;
	    GalleryRequest.sendPOST(GALLERY_SERVER_URL + "images/"+pItemId+"/comment", data, pCallback_addComment, socialType);
	}
	 
	 /**
	 * allows user to share item
	 * itemId - required, unique Id of item, only owner of item can share
	 * callback_share - name of callback method where response will 
	 */
	 this.share = function(itemId, callback_share){
	    var data = "socialId=" + galleryUserId + "&socialType="+ socialType;
	    GalleryRequest.sendPOST(GALLERY_SERVER_URL + "images/"+itemId+"/share", data, callback_share, socialType);
	 }
	 
	 /**
	 * allows user to share item
	 * itemId - required, unique Id of item, only owner of item can share
	 * callback_unshare - name of callback method where response will 
	 */
	 this.unshare = function(itemId, callback_unshare){
	    var data = "socialId=" + galleryUserId + "&socialType="+ socialType;
	    GalleryRequest.sendPOST(GALLERY_SERVER_URL + "images/"+itemId+"/unshare", data, callback_unshare, socialType);
	 }
	 
	 /**
	 * allows user to share item with some other user
	 * itemId - required, unique Id of item, only owner of item can share
	 * callback_shareWithSomeone - name of callback method where response will 
	 */
	 this.shareWithSomeone = function(itemId, sharedSocialId, sharedSocialType, callback_share, 
			 sharedSocialName, sharedSocialThumbUrl, sharedSocialProfileUrl){
	    var data = "socialId=" + galleryUserId + "&socialType="+ socialType;
	    data += "&sharedSocialId=" + sharedSocialId + "&sharedSocialType="+ sharedSocialType;
	    data += typeof sharedSocialName == 'undefined' || sharedSocialName==null ? '' : "&sharedSocialName=" + encodeURIComponent(sharedSocialName)
	    data += typeof sharedSocialThumbUrl == 'undefined' || sharedSocialThumbUrl==null ? '' : "&sharedSocialThumbUrl=" + encodeURIComponent(sharedSocialThumbUrl);
	    data += typeof sharedSocialProfileUrl == 'undefined' || sharedSocialProfileUrl==null ? '' : "&sharedSocialProfileUrl=" + encodeURIComponent(sharedSocialProfileUrl);
	    GalleryRequest.sendPOST(GALLERY_SERVER_URL + "items/"+itemId+"/sharewith", data, callback_share, socialType);
	 }
	 
	/**
	 * saves item
	 * publish - indicate whter item saved privately or published into gallery
	 * title - user provited title for item
	 * callback_saveItem - callback method to which response will return
	 */
	this.saveItem = function(published, title, callback_saveItem, pSocialType, pItemType, pCategory, pDescription, pProperty1){
		published = typeof published=='undefined' || published==null  ? (typeof currentPublished=='undefined' ? Gallery.UNPUBLISHED_KEY : currentPublished) : published;
		pSocialType = typeof pSocialType == 'undefined' || pSocialType==null ? socialType : pSocialType;
		pItemType = typeof pItemType == 'undefined' || pItemType==null ? itemType : pItemType;  
		category = typeof pCategory == 'undefined' || pCategory==null ? category : pCategory; 
		pDescription = typeof pDescription == 'undefined' || pDescription==null ? '' : pDescription;
		pProperty1 = typeof pProperty1 == 'undefined' || pProperty1==null ? '' : pProperty1;
		
			var data = "uploadToken="+tempKey+
						"&model.title="+encodeURIComponent(title)+
						"&model.user.socialId="+galleryUserId+
						"&model.user.socialName="+encodeURIComponent(galleryUserName)+
						"&model.user.socialType="+pSocialType+
						"&model.user.socialProfileUrl="+galleryUserProfile+
						"&model.user.socialThumbUrl="+galleryUserThumbnail+
						"&model.status="+published+
						"&model.itemType="+pItemType+
						"&model.category="+encodeURIComponent(category)+
						"&model.source="+sourceApp+
						"&model.description="+encodeURIComponent(pDescription)+
						"&model.property1="+encodeURIComponent(pProperty1);
			GalleryRequest.sendGET(GALLERY_SERVER_URL+"images/upload-step2-commit?"+data,callback_saveItem, socialType);
		}
	 
	 	/**
		 * Updates an item.
		 *  
		 * Parameters:
		 * pId - item id - REQUIRED - unique identifier for an item, which is enough to find and do an updates, it is not updateable field but required one.
		 * pCategory - category/folder to which belong an item - it is optional if not provided should be null.
		 * pTitle - title of an item - it is optional if not provided should be null.
		 * pProperty1 - a free property number 1 of an item - it is optional if not provided should be null.
		 * pCallbackUpdateItem - callback method to which response will return.
		 */
		this.updateItem = function(pId, pCategory, pTitle, pDescription, pProperty1, pCallbackUpdateItem){
			if(pId = typeof pId=='undefined' || pId==null) {alert('ID is required parameter!'); return false;};
			/*sourceApp, socialType and socialId are taken from Gallery initiated parameters*/
			var data = 	"model.id="+pId+
						"&model.source="+sourceApp+
						"&model.user.socialType="+socialType+
						"&model.user.socialId="+galleryUserId;
			
			data += (typeof pCategory == 'undefined' || pCategory==null) ? "" : "&model.category="+pCategory; 
			data += (typeof pTitle == 'undefined' || pTitle==null) ? "" : "&model.title="+pTitle; 
			data += (typeof pDescription == 'undefined' || pDescription==null) ? "" : "&model.description="+pDescription;
			data += (typeof pProperty1 == 'undefined' || pProperty1==null) ? "" : "&model.property1="+pProperty1;
			
			GalleryRequest.sendPOST(GALLERY_SERVER_URL + "items/"+pId+"/update", data, pCallbackUpdateItem, socialType);
		}
		 
		/**
		 * Add Category to a user of a for an app
		 * http://justlocate.com/gallery/categories/[source]/[socialId]/[yourCategegory]/add
		 */
		this.addCategory = function(pCategory, pCallbackAddCategory){
			GalleryRequest.sendGET(GALLERY_SERVER_URL + "categories/"+source+"/"+galleryUserId+"/"+pCategory+"/add", pCallbackAddCategory, socialType);
		}
		
		/**
		 * Delete Category to a user of a for an app
		 * http://justlocate.com/gallery/categories/[source]/[socialId]/[yourCategegory]/delete
		 */
		this.deleteCategory = function(pCategory, pCallbackDeleteCategory){
			GalleryRequest.sendGET(GALLERY_SERVER_URL + "categories/"+source+"/"+galleryUserId+"/"+pCategory+"/delete", pCallbackDeleteCategory, socialType);
		}
		
		/**
		 * Delete Category to a user of a for an app
		 * http://justlocate.com/gallery/categories/[source]/[socialId]/[yourCategegory]/delete
		 */
		this.categories = function(pCallbackCategories){
			GalleryRequest.sendGET(GALLERY_SERVER_URL + "categories/"+source+"/"+galleryUserId+"/json", pCallbackCategories, socialType);
		}
	 
	//~server calls
	
	

	this.init = function(){
		if(typeof columns != "undefined" && columns != null){
			COL_COUNT = columns;
		}
		if(typeof limit != "undefined" && limit != null){
			PAGE_LIMIT = limit;
		}
		if(typeof pSourceApp != "undefined" && pSourceApp != null){
			sourceApp = pSourceApp;
		}
		this.context["source"] = sourceApp;
		if(typeof tag_name_list != "undefined" && tag_name_list != null){
			tagNameList = tag_name_list;
		}
		if(typeof tag_cloud_position != "undefined" && tag_cloud_position != null){
			tagCloudPosition = tag_cloud_position;
		}
		if(typeof afterSaveCallBack != "undefined" && afterSaveCallBack != null){
			afterSaveCallBackGlob = afterSaveCallBack;
		}
		if(typeof click_CallBack != "undefined" && click_CallBack != null){
			clickCallBack = click_CallBack;
		}
		if(typeof social_type != "undefined" && social_type != null){
			socialType = social_type;
		}
		this.context["socialType"] = socialType;
		if(typeof item_type != "undefined" && item_type != null){
			itemType = item_type;
		}
		this.context["itemType"] = itemType;
		
		if(typeof pCategory != "undefined" && pCategory != null){
			category = pCategory;
		}
		this.context["category"] = category;
		
		
	    if (G_IS_LIVE && G_IS_OPENSOCIAL) {
	        galleryUserId = user.getId();
			if(galleryUserId.lastIndexOf(":")) galleryUserId = galleryUserId.substring(galleryUserId.lastIndexOf(":")+1);
			//galleryUserId = parseInt(galleryUserId.substring(galleryUserId.lastIndexOf(":")+1));
	        galleryUserThumbnail = user.getField(opensocial.Person.Field.THUMBNAIL_URL);
	        galleryUserName = user.getField(opensocial.Person.Field.NAME).fields_.unstructured;
			if(typeof galleryUserName == "undefined") 
  			galleryUserName = user.getDisplayName();
	        galleryUserProfile = user.getField(opensocial.Person.Field.PROFILE_URL);
	    }
		else{
	        galleryUserId = user["galleryUserId"];
	        galleryUserThumbnail = user["galleryUserThumbnail"];
	        galleryUserName = user["galleryUserName"];
	        galleryUserProfile = user["galleryUserProfile"];
		}
	    this.context["socialId"] = galleryUserId;
	    this.context["socialThumbUrl"] = galleryUserThumbnail;
	    this.context["socialName"] = galleryUserName;
	    this.context["socialProfileUrl"] = galleryUserProfile;
	}//end init
	
	

	
///sample view
		
	var tagList = function(){
		self.getTags(resp_tagList);
	}

	var resp_tagList = function(response){
		var data = response.data;
		if(tagNameList != ""){
			currentTag = "";
			for(var i = 0; i < data.relativeTags.length; i++){
				currentTag += data.relativeTags[i].id + ",";
			}
			currentTag = currentTag.substring(0, currentTag.length-1);
			for(var i = 0; i < data.tags.length; i++){
				allTagsForImages[i] = data.tags[i];
			}
		}
		var str = get_tags_html(data.relativeTags);
		document.getElementById("glr_tagsDiv").innerHTML = str;
		var tag_all = document.getElementById("glr_tag_all");
		tag_all.onclick = function(){
							self.defineCurrentTag(0);
						}
		for(var i = 0; i < data.relativeTags.length; i++){
			var tag = document.getElementById("glr_tag_"+i);
			if(tag){
				tag.onclick = function(){
								self.defineCurrentTag(this.getAttribute("tagId"));
							}
			}
		}
		$("#xList").tagcloud({type:"list"}).find("li").tsort("rand");
		
		
	    self.getImageList(currentPage);
	}

	var get_tags_html = function(tags){
		
		var str = "<span id='glr_tag_all' class='glr_tag_all'><span>All</span></span>"+
				"<ul id='xList' class='xmpl' style='display:inline;'>";
		for(var i = 0; i < tags.length; i++){
			str+="<li title='"+tags[i].name+" '"+"value='"+tags[i].value+"'>";
			str+="<span id='glr_tag_"+i+"' tagId='"+tags[i].id+"'>"+tags[i].name+"</span> ";
		}
		str+="</ul>";
		return str;
	}
	
	this.defineCurrentTag = function(tagId){
		if(tagId == 0 && tagNameList != ""){
			currentTag = "";
			for(var i = 0; i < allTagsForImages.length; i++){
				currentTag += allTagsForImages[i].id + ",";
			}
			currentTag = currentTag.substring(0, currentTag.length-1);
		}else{
			currentTag = tagId;
		}
		self.getImageList(0);
	}
	/*deprecated*/
	this.saveImage = function(published){
		self.saveItem(published, document.getElementById("titleText").value, resp_saveImage, "myspace", "img");
	}
	
	this.saveAndPublish = function(title){
		self.saveItem(1, title, resp_saveImage, socialType, itemType);
	}

	var resp_saveImage = function(response){
	    var data = response.data;
		if (data.error) {
			document.getElementById("errorTd").innerHTML=data.error;
		}else{
			eval(afterSaveCallBackGlob + "('" + GALLERY_SERVER_URL + "images/"+data.image.id + "', data.image.id,data.image.published)");
		}
	}
	//end sample view
	
   
   //triger initialization
   self.init();
	
}//end constructor

///////////////////////////////////////////////////////////////////////////
var GalleryRequest = new Object();
GalleryRequest.send = function(url, method, responseHandler, data, urlencoded){
    var req;
    if (window.XMLHttpRequest) {
        req = new XMLHttpRequest();
    }
    else 
        if (window.ActiveXObject) {
            req = new ActiveXObject("Microsoft.XMLHTTP");
        }
    req.onreadystatechange = function(){
        if (req.readyState == 4) {// only if req shows "loaded"
            if (req.status < 400) {// only if "OK"
                try {
                    req.data = eval("(" + req.responseText + ")");
                } 
                catch (ex) {
                    console.log(ex);
                }
                req.text = req.responseText;
                responseHandler(req);
            }
        }
    }
    if (method == "POST") {
        req.open("POST", url, true);
        if (urlencoded) 
            req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        req.send("" + data);
    }
    else {
        req.open("GET", url, true);
        req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        req.send(null);
    }
    
    return req;
}

GalleryRequest.sendPOST = function(url, data, responseHandler, socialType){
	if(G_IS_LIVE){
		switch(socialType){
			case "facebook":
			case "osebe":
				if (typeof data == 'undefined'){
		            data = '';
				}
				data += "&redirect="+encodeURIComponent(url);
				url = GALLERY_PROXY_URL;
		        GalleryRequest.send(url, "POST", responseHandler, data, true);
		        break;
		    default:
				var os_params = {};
				os_params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
				os_params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
				os_params[gadgets.io.RequestParameters.POST_DATA] = data;
				gadgets.io.makeRequest(url, responseHandler, os_params);
				break;
		}
	}else{
		if(undefined == data){
			data = '';
		}
		GalleryRequest.send(url, "POST", responseHandler, data, true);
	}
}

GalleryRequest.sendGET = function(url, responseHandler, socialType){
	if(G_IS_LIVE){
		switch(socialType){
			case "facebook":
			case "osebe":
				url = GALLERY_PROXY_URL + "&redirect="+encodeURIComponent(url);
		  		return GalleryRequest.send(url, "GET", responseHandler);
		  		break;
		  	default:
		  		var os_params = {};
				os_params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
				os_params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
				gadgets.io.makeRequest(url, responseHandler, os_params);
				break;
		}
	}else{
		if(GALLERY_USE_PROXY){
			url = GALLERY_PROXY_URL + "&redirect="+encodeURIComponent(url);
	  		GalleryRequest.send(url, "GET", responseHandler);
		}else{
			GalleryRequest.send(url, "GET", responseHandler);
		}
		
	}
}


//// get current time

var getCurrentTime = function(){
    var timeNow = new Date();
    var hours   = timeNow.getHours();
    var minutes = timeNow.getMinutes();
    var seconds = timeNow.getSeconds();
    var timeString = "" + ((hours > 12) ? hours - 12 : hours);
    timeString  += ((minutes < 10) ? ":0" : ":") + minutes;
    timeString  += ((seconds < 10) ? ":0" : ":") + seconds;
    
   return timeString;
 } 
