﻿var Ads={
	init:function () {
		if (!$("ads")) return;

		Ads._initMenuLinks();
		Ads._initAdItemsOpen();
		Ads._initInfiniteScroll();
		Ad._initCloseButton();
		Ads._setMaximums();

		$("ads-wrap").store("minimizeFx",$("ads-wrap").effects({wait:false}));

		Case.addEvent("onOpening",Ad.close.bind(Ad));
		
		FullAd.addEvent("onOpening",function () {
			Ads.abortSearch();
			Ads._abortInfiniteScroll();
		});
	},

	maximums:null,

	_setMaximums:function () {
		Ads.maximums={ right:$("ads-wrap").offsetWidth,bottom:$("ads-wrap").scrollHeight };
	},

	_initMenuLinks:function () {
		var makeCurrent=function (a) {
			a.getParent().getParent().getElement(".current").removeClass("current");
			a.getParent().addClass("current");
		};
	
		$("menu-all-projects").addReplacingEvent("click",function (e) {
			Ads.topRated=false;
			Ads.editorsChoice=false;
			Ads.searchTerms=null;
			Ads.searchTags=null;
			Ads.searchWithProperties();
			makeCurrent(this);
		});
		$("menu-top-rated").addReplacingEvent("click",function (e) {
			Ads.topRated=true;
			Ads.editorsChoice=false;
			Ads.searchTerms=null;
			Ads.searchTags=null;
			Ads.searchWithProperties();
			makeCurrent(this);
		});
		$("menu-editors-choice").addReplacingEvent("click",function (e) {
			Ads.topRated=false;
			Ads.editorsChoice=true;
			Ads.searchWithProperties();
			makeCurrent(this);
		});
	},

	_initAdItemsOpen:function () {
		$("ads").delegateEvent("click","li",function (e) {
			var adId=+this.id.split("-").pop(); // a id in format ad-47
			Ad.open(adId,this);
		},true,true);
	},

	_initAdItems:function () {
		if (Browser.Engine.trident4) return;		
		$("ads").getElements("li").each(function (li) {
			Ads._applyNewAdEffect(li);
			// append lowlight element if not ie cause ie has gray() filter
			if (!Browser.Engine.trident) li.adopt(new Element("span",{"class":"lowlight"}));
		});
	},

	_applyNewAdEffect:function (el) {
		if(!Browser.Engine.trident4) {
			el.effects({duration:500}).start({opacity:1});
		}
	},

	_lowlightOtherAds:function () {
		if (Browser.Engine.trident4) return;
		$("ads").addClass("gray");
		// when the .gray class affected li img elements browser wouldn't respond after focusing an input... so manually change filter
		if (Browser.Engine.trident) $("ads").getElements("li>img").each(function (img) {
			if (img.retrieve("lowlight")) return;
			img.store("lowlight",true);
			img.setStyle("filter","gray()");
		});
	},
	_highlightOtherAds:function () {
		if (Browser.Engine.trident4) return;
		$("ads").removeClass("gray");
		if (Browser.Engine.trident) $("ads").getElements("li>img").setStyle("filter","").store("lowlight",false);
	},

	// Loading Search Results
	pageIndex:1,

	_fillPageTimeout:null,
	
	_infiniteScrollInitiated:false,

	_initInfiniteScroll:function () {
		if (Ads._infiniteScrollInitiated) return;
		Ads._infiniteScrollInitiated=true;

		Ads._callDelayedFillPageUntillScrolled();
		var scrollAndFetchMoreAds=function (e) {
			$clear(Ads._fillPageTimeout); // don't fetch if still scrolling!
			Ads._callDelayedFillPageUntillScrolled();
		};
		addEvent("scroll",scrollAndFetchMoreAds);
		addEvent("resize",scrollAndFetchMoreAds);

		Lightbox.addEvent("onBeforeShow",function () {
			removeEvent("scroll",scrollAndFetchMoreAds);
		});
		Lightbox.addEvent("onAfterHide",function () {
			addEvent("scroll",scrollAndFetchMoreAds);
		});
	},
	_abortInfiniteScroll:function () {
	
		Ads._fillPageTimeout=$clear(Ads._fillPageTimeout); // don't fetch if still scrolling!
		Ads._infiniteScrollInitiated=false;
	},
	_callDelayedFillPageUntillScrolled:function () {
		Ads._fillPageTimeout=Ads._fillPageUntillScrolled.delay(500);
	},

	_fillPageUntillScrolled:function () {
		if (Ads._canPageHaveMoreAdsWithoutScrolling() && !Ads.noMoreResults) Ads._fetchNextPage();
	},

	PRELOAD_DISTANCE:150,

	_canPageHaveMoreAdsWithoutScrolling:function () {
		/*
		__________________ -----------------
		|             |  | --				|
		|             |  |   |== (1)		|
		|             |  | --				|
		|             |||| --				|
		|             ||||   |				|
		|             ||||   |== (2)		|== (3)
		|             ||||   |				|
		|             |||| --				|
		|             |  | ----------------|----|
		|             |  |					|    |== (4)
		|             |  |                 |    |
		|_____________|__|-----------------|----|
		
		(1) document.getScroll().y (all what's scrolled from top)
		(2) document.getSize().y (visible window area)
		(3) document.getScrollSize().y (all content including overflown height)
		(4) 'scrollBottom' (1-2-3)

		when scroll from bottom is less than PRELOAD_DISTANCE, retutn true so the interval can load more data
		*/
		return document.getScrollSize().y-document.getScroll().y-document.getSize().y<Ads.PRELOAD_DISTANCE;
	},
 
	_fetchNextPage:function () {
		++Ads.pageIndex;
		Ads._fetchByProperties(true,function () {
			if (!Ads.noMoreResults) Ads._callDelayedFillPageUntillScrolled();
		});
	},

	// indicates whether there are more results from the server
	// this variable is initialized @ Ads.ascx when there are no more results to display
	// when set to true interval is cleared
	noMoreResults:false,

	searchTerms:null, // string[]
	searchTags:null, // int[]
	topRated:false,
	editorsChoice:false,

	searchWithProperties:function () {
		Ads.search(Ads.searchTerms,Ads.searchTags,Ads.topRated,Ads.editorsChoice);
	},
	
	// commits search by terms and tags
	// terms - an array of strings of search tersms
	// tags - an array of ad tag ids
	_lastSearch:JSON.encode([null,null,false,false]), // initial search
	search:function (searchTerms,searchTags,topRated,editorsChoice) {
		if (!Ads._isListOpened) Ads.showList();

		Ads.fireEvent("onSearching",$A(arguments));

		// prevent searching for same args
		var currentSearch=JSON.encode($A(arguments));
		if (currentSearch==Ads._lastSearch) return;

		Ads._lastSearch=currentSearch;

		// reset current results
		$("ads").empty();
		$("ads-wrap").addClass("loading");
		if ($defined(searchTerms)) Ads.searchTerms=searchTerms;
		if ($defined(searchTags)) Ads.searchTags=searchTags;
		if ($defined(topRated)) Ads.topRated=topRated;
		if ($defined(editorsChoice)) Ads.editorsChoice=editorsChoice;
		Ads.pageIndex=1;
		// reset the noMoreResults variable
		Ads.noMoreResults=false;
		// fetch source of page one for these terms
		Ads._fetchByProperties(false,function () { Ads._callDelayedFillPageUntillScrolled(); });
	},

	// searches for ads according to the members searchTerms/searchTags/pageIndex
	// when done - adopts the results into '#ads'
	// adoptResults - whether to adopt the results or clear #ads and then adopt them (for next page)
	_fetchByProperties:function (adoptResults,callback) {
		if (!$("ads-wrap").hasClass("loading")) $("ads-wrap").addClass("fetching");

		// ajax request
		Mantis.EyeBlaster.Services.AdService.GetAdsResultSource(Ads.searchTerms || [],Ads.searchTags || [],Ads.topRated || false,Ads.editorsChoice || false,Ads.pageIndex || 1,function (source) {
			if(window.document.location.pathname.indexOf('blocks.aspx')>-1 && Ads.noMoreResults) {
				return;
			}
			var elements=Element.fromMarkup(source,true);
			if (adoptResults) Ads.adoptResults(elements);
			else Ads.setAdResults(elements); // true - multiple elements, returns an array

			if (callback) callback();
			
			$("ads-wrap").retrieveOrStore("minimizePaddingFx",function () { return this.effect("paddingBottom") }).start(Ads.noMoreResults ? 0 : 50);
			// new ads are here, just make sure to low light all others if needed (a preview is opened)
			if (Ad._isOpened) Ads._lowlightOtherAds();

			Ads.fireEvent("onSearched",[Ads.searchTerms,Ads.searchTags,Ads.topRated,Ads.editorsChoice]);

			// after recieving data - delete the reference
			Ads._currentSearchRequest=null;
		});
	},
	
	abortSearch:function () {
		if (Ads._currentSearchRequest) Ads._currentSearchRequest.abort();
		Ads._currentSearchRequest=null;
	},

	setAdResults:function (elements) {
		$("ads").empty();
		Ads.adoptResults(elements);
	},
	adoptResults:function (elements) {
		$("ads-wrap").removeClass("loading").removeClass("fetching");
		if(!Browser.Engine.trident4){
			elements.setStyles({opacity:0});			
			$("ads")
				.setStyles({overflow:"hidden",height:$("ads").offsetHeight})
				.adopt(elements)
				.retrieveOrStore("effect",function () { return this.effect("height",{wait:false}); })
				.start($("ads").scrollHeight).chain(function () {
					// in the end set height to auto and overflow:visible
					$("ads").setStyles({overflow:"",height:""});
					Ads._setMaximums.delay(10);
				});
		}else{
			$("ads").setStyles({overflow:"",height:""}).adopt(elements);
			Ads._setMaximums.delay(10);
		}		
		// init all ads and their events
		Ads._initAdItems();
	},

	_isListOpened:true,
	hideList:function () {
		Ads.fireEvent("onHiding");
		Ads._isListOpened=false;
		
		if (!Browser.Engine.trident4){	
			$("ads-wrap")
				.setStyles({overflow:"hidden"})
				.retrieve("minimizeFx").start({opacity:0,height:0}).chain(function () {
					$("ads-wrap").hide();
					Ads.fireEvent("onHid");
				});
		}		
		else{
			$("ads-wrap").setStyles({overflow:"hidden",height:0});
			$("ads-wrap").hide();
			Ads.fireEvent("onHid");
		}		
	},
	showList:function () {
		Ads._initInfiniteScroll();
	
		var wrap=$("ads-wrap");
	
		Ads.fireEvent("onShowing");
		Ads._isListOpened=true;
		var finalHeight=wrap.scrollHeight;
		var retries=5;
		wrap.show();

		// wrap.scrollHeight is 0 sometimes.. try 5 times
		var iv=(function () {
			retries--;
			finalHeight=wrap.getScrollSize().y;
		
			if (retries==0) {
				iv=$clear(iv);
				return callback();
			}
			
			if (finalHeight>=0) {
				if(!Browser.Engine.trident4){
					wrap.retrieve("minimizeFx").start({height:finalHeight,opacity:1}).chain(callback);
				}else{
					wrap.setStyle("height",finalHeight);
					callback();
				}
				iv=$clear(iv);
			}
		}).periodical(50);

		function callback() {
			wrap.setStyles({overflow:"",height:"",opacity:1});
			Ads.fireEvent("onShown");
		}
	}
};
$DL(Ads.init);
Events.makeObjectEventable(Ads);

