function initializeSearch(form, view, options) {

	form = $(form);
	view = $(view);
	options = options || {};
	if (options.weeklyTag) weeklyTag = options.weeklyTag;

	if (form && view) {
		var itunesSearch = new iTunesSearch(form, view, 'PT', options);

		//if a weeklytag was given, apply it to links in the weekly module
		if (typeof(weeklyTag) != 'undefined') {

			AC.Tracking.tagLinksWithin(view, 'v0', weeklyTag, function(link) {
				if (link.href) {					
					return !!(link.href.match(/itms:\/\/|phobos/));
				} else {
					return false;
				}
			});
		}
	}
}



if (typeof(Search) == 'undefined') { Search = {}; }

Search.DirectCallbacks = [];
 
/**
 * Base class for search requests which directly hit a json service
 */
Search.DirectRequest = function() {};
Search.DirectRequest.prototype = {
	
	s: null,
	r: null,
	url: null,
	options: null,
	
	baseInitialize: function(server, request, options) {
		
		this.s = server;
		this.r = request;
		
		this.options = options;
		
		if (!this.options) {
			options = [];
		}
		
		if (typeof(this.options.onSuccess) != 'function') {
			this.options.onSuccess = Prototype.emptyFunction;
		}
		
		if (typeof(this.options.onFailure) != 'function') {
			this.options.onFailure = Prototype.emptyFunction;
		}
		
		this.url = this.s + this.r + '&output=json';
	},
	
	execute: function() {
		
		var callback = this.parseResponse.bind(this);
		Search.DirectCallbacks.push(callback);
		var callbackNumber = Search.DirectCallbacks.length - 1;
	
		var callbackString = encodeURIComponent('Search.DirectCallbacks[' + callbackNumber + ']');
		
		var scriptNode = document.createElement('script');
		scriptNode.setAttribute('charset', 'utf-8');
		scriptNode.setAttribute('type', 'text/javascript');
		scriptNode.setAttribute('src', this.url + '&callback=' + callbackString);
		
		var head = document.getElementsByTagName('head')[0];
		
		head.appendChild(scriptNode);
	},
	
	abort: Prototype.emptyFunction,
	
	parseResponse: function(response) {}
	
};

/**
 * Search that hits iTunes services directly
 * Tries to provide same client interface as any other search
 */
Search.iTunesSearchRequest = Class.create();
Object.extend(Search.iTunesSearchRequest.prototype, Search.DirectRequest.prototype);
Object.extend(Search.iTunesSearchRequest.prototype, {
	
	s: 'http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZStoreServices.woa/wa/itmsSearch',
	afterParsing: Prototype.emptyFunction,
	
	initialize: function(request, options) {
		this.baseInitialize(this.s, request, options);
		this.afterParsing = this.options.onSuccess;
		this.options.onSuccess = this.parseResponse.bind(this);
	},
	
	parseResponse: function(response) {
		var results = {itunes: response.results};
		this.afterParsing(this, results);
	}
});

var iTunesSearch = Class.create();
Object.extend(iTunesSearch.prototype, Event.Listener);
Object.extend(iTunesSearch.prototype, {
	
	form: null,
	searchField: null,

	recentTerm: null,
	
	recentPanel: null,
	
	searches: null,
	
	failures: 0,
	successes: 0,
	
	country: 'UK',
	
	initialize: function(form, wrapper, country, options) {
		this.searches = [];
		
		this.form = $(form);
		this.wrapper = $(wrapper);
		this.country = country;
		this.options = options || {};
		
		this.form.getElementsByClassName('search-submit')[0].hide();
		
		this.searchField = this.form.getElementsByClassName('search-field')[0];
		
		this.form.observe('submit', function(evt) {
			Event.stop(evt);
			var term = this.searchField.value; //TODO escape term as necessary
			this.search(term);
		}.bind(this));
		
		//TODO observe esc key/clearing search field as way to close search results
	},
	
	search: function(term) {
		
		this.searches = [];
		this.failures = 0;
		this.successes = 0;
		
		this.recentTerm = term;
		
		if (this.resultsPanel) {
			this.resultsPanel.remove();
		}
		this.resultsPanel = $(document.createElement('div'));
		this.resultsPanel.addClassName('search-results');
		if(!AC.Detector.isIE()) this.resultsPanel.addClassName('loading');
		this.wrapper.appendChild(this.resultsPanel);
		
		var header = $(document.createElement('h3'));
		header.innerHTML = "Procurar por '" + this.recentTerm + "'";
		header.addClassName('header');
		this.resultsPanel.appendChild(header);

		var progress = $(document.createElement('div'));
		progress.addClassName('progress');
		progress.innerHTML = "a procurar";
		this.resultsPanel.appendChild(progress);

		var closeButton = $(document.createElement('a'));
		closeButton.addClassName('close');
		closeButton.innerHTML = "Terminar pesquisa";
		closeButton.observe('click', function(evt) {
			Event.stop(evt);
			this.stop();
		}.bind(this));
		
		this.resultsPanel.appendChild(closeButton);

		var limit = this.options.limit || 3;

		var albumSearch = new ScopedSearch(this.recentTerm, this.resultsPanel, "Alb&uacute;ns", {media: 'music', entity: 'album', limit: limit, country: this.country});
		var songSearch = new ScopedSearch(this.recentTerm, this.resultsPanel, "Faixas", {media: 'music', entity: 'musicTrack', limit: limit, country: this.country});
		var moviesSearch = new ScopedSearch(this.recentTerm, this.resultsPanel, "Filmes", {media: 'movie', entity: 'movie', limit: limit, country: this.country});
		var tvshowsSearch = new ScopedSearch(this.recentTerm, this.resultsPanel, "Sˇries de TV", {media: 'tvShows', entity: 'tvSeason', limit: limit, country: this.country});
		var podcastSearch = new ScopedSearch(this.recentTerm, this.resultsPanel, "Podcasts", {media: 'podcast', entity: 'podcast', limit: limit, country: this.country});
		
		this.otherSearches = $(document.createElement('div'));
		this.otherSearches.addClassName('also-search');
		
		var otherHeader = document.createElement('h3');
		Element.addClassName(otherHeader, 'header');
		otherHeader.innerHTML = 'Ver tamb&eacute;m';
		this.otherSearches.appendChild(otherHeader);
		
		this.resultsPanel.appendChild(this.otherSearches);
		
		var musicVideoSearch = new QuickScopedSearch(this.recentTerm, this.otherSearches, "V&iacute;deos de M&uacute;sica", {media: 'musicVideo', entity: 'musicVideo', limit: 1, country: this.country});
		var audiobookSearch = new QuickScopedSearch(this.recentTerm, this.otherSearches, "Livros &Aacute;udio", {media: 'audiobook', entity: 'audiobook', limit: 1, country: this.country});
		
		//TODO classing the scoped search based on media type for resizing art?
		
		this.searches = this.searches.concat([albumSearch, songSearch, moviesSearch, tvshowsSearch, podcastSearch, musicVideoSearch, audiobookSearch]);
		
		for (var i = 0; i < this.searches.length; i++) {
			this.listenForEvent(this.searches[i], 'onNoResults', false, this.acknowledgeNoResults.bind(this));
			this.listenForEvent(this.searches[i], 'onResults', false, this.acknowledgeResults.bind(this));
			this.searches[i].search();
		}
	},
	
	stop: function() {
		
		if (this.resultsPanel) {
			this.resultsPanel.remove();
			this.resultsPanel = null;
		}
		
		return false;
		//TODO kill al open requests?
	},
	
	acknowledgeResults: function() {
		this.successes++;
		
		if (this.failures + this.successes == this.searches.length) {
			this.reportResults();
		}
	},
	
	acknowledgeNoResults: function() {
		this.failures++;
		
		if (this.searches.length == this.failures) {
			this.reportNoResults();
		} else if (this.failures + this.successes == this.searches.length) {
			this.reportResults();
		}
	},
	
	reportResults: function() {
		
		//if none of the alternate searches came back, hide the column
		if ($A(this.otherSearches.getElementsByTagName('a')).length <= 0) {
			this.otherSearches.hide();
		}
		
		$(this.resultsPanel.getElementsByClassName('progress')[0]).remove();
		this.resultsPanel.removeClassName('loading');
		
	},
	
	reportNoResults: function() {
		
		this.resultsPanel.innerHTML = '';
		this.resultsPanel.removeClassName('loading');
		this.resultsPanel.addClassName('no-results');
		
		var notice = document.createElement('h3');
		notice.innerHTML = 'Lamentamos, mas a sua pesquisa n&atilde;o conseguiu encontrar qualquer resultado.';
		this.resultsPanel.appendChild(notice);
		notice = null;
		
		var instructions = document.createElement('p');
		instructions.innerHTML = 'Tente pesquisar novamente, ou ';
		
		var storeLink = document.createElement('a');
		storeLink.setAttribute('href', 'http://phobos.apple.com/WebObjects/MZStore.woa/wa/storeFront');
		storeLink.innerHTML = 'navegue na iTunes store';
		instructions.appendChild(storeLink);
		instructions.innerHTML += '.';
		storeLink = null;
		
		this.resultsPanel.appendChild(instructions);
		instructions = null;
		
		var close = $(document.createElement('a'));
		close.addClassName('verbose-close');
		close.innerHTML = 'fechar';
		this.resultsPanel.appendChild(close);
		
		close.onclick = this.stop.bind(this);
		
	}
	
});


var ScopedSearch = Class.create();
Object.extend(ScopedSearch.prototype, Event.Publisher);
Object.extend(ScopedSearch.prototype, {
	
	term: null,
	container: null,
	options: null,
	label: null,
	
	awaitingResponse: null,
	
	initialize: function(term, container, label, options) {
		
		this.term = term;
		this.container = $(container);
		this.options = options || {};
		this.label = label;
		
		this.render();
	},
	
	render: function() {
		this.resultsPanel = $(document.createElement('div'));
		this.resultsPanel.addClassName('category');
		this.resultsPanel.addClassName('loading');
		
		var heading = document.createElement('h3');
		Element.addClassName(heading, 'heading');
		heading.innerHTML = this.label;
		this.resultsPanel.appendChild(heading);
		
		this.resultsList = $(document.createElement('span'));
		this.resultsPanel.appendChild(this.resultsList);
		
		this.container.appendChild(this.resultsPanel);
	},
	
	search: function() {
		
		var country = this.options.country || 'PT';
		this.limit = this.options.limit || 1;
		
		var media = this.options.media || 'all';
		var entity = this.options.entity ? '&entity=' + this.options.entity : ''; 
		
		var requestUrl = '?media=' + media + entity + '&country=' + country + '&limit=' + this.limit + '&term=' + this.term;
		
		var request = new Search.iTunesSearchRequest(requestUrl, {
			onSuccess: this.parseResults.bind(this)})
		
		request.execute();
		
		this.awaitingResponse = setTimeout(this.reportNoResults.bind(this), 15000);
		
	},
	
	parseResults: function(request, response) {
	
		clearTimeout(this.awaitingResponse);
		
		if (this.resultsList) {
			this.resultsList.remove();
		}
		this.resultsPanel.removeClassName('loading');
		
		if (response.itunes.length > 0) {
			this.reportResults(response.itunes);
		} else {
			this.reportNoResults();
		}
	},
	
	reportResults: function(data) {
		
		this.dispatchEvent('onResults', this);
		
		this.resultsList = document.createElement('ul');

		for (var i = 0; i < data.length; i++) {
			var resultData = data[i];
			var result = $(document.createElement('li'));

			if (i < 2*this.limit/3) {
				
				result.addClassName('art')
				
				var art = document.createElement('img');
				art.setAttribute('src', resultData.artworkUrl60);

				var artLink = document.createElement('a');
				Element.addClassName(artLink, 'thumb');
				artLink.setAttribute('href', resultData.itemLinkUrl);
				artLink.appendChild(art);

				result.appendChild(artLink);
			}

			var link = document.createElement('a');
			Element.addClassName(link, 'title');
			link.setAttribute('href', resultData.itemLinkUrl);
			link.innerHTML = resultData.itemCensoredName.truncate(16);
			result.appendChild(link);

			var artistLink = document.createElement('a');
			artistLink.setAttribute('href', resultData.artistLinkUrl);
			artistLink.innerHTML = resultData.artistName.truncate(16);
			result.appendChild(artistLink);

			this.resultsList.appendChild(result);
		}
		
		this.resultsPanel.appendChild(this.resultsList);

		var media = this.options.media || 'all'; //TODO replace hardcoded feault here with a default property on this class		
		var entity = (this.options.entity && this.options.entity != 'musicTrack') ? '&entity=' + this.options.entity : '';
		
		var storeUrl = "http://ax.phobos.apple.com.edgesuite.net/WebObjects/MZSearch.woa/wa/com.apple.jingle.search.DirectAction/search?submit=seeAllLockups&term=" + this.term + "&media=" + media + entity;
		
		var storeLink = $(document.createElement('a'));
		storeLink.setAttribute('href', storeUrl);
		storeLink.addClassName('store');
		storeLink.innerHTML = 'Ver tudo no iTunes';
		this.resultsPanel.appendChild(storeLink);
		
	},
	
	reportNoResults: function() {

		this.resultsPanel.addClassName('no-results');
		
		this.resultsList = document.createElement('span');
		this.resultsList.innerHTML = "Sem resultados";
		this.resultsPanel.appendChild(this.resultsList);
		
		this.dispatchEvent('onNoResults', this);
	}
	
});

var QuickScopedSearch = Class.create();
Object.extend(QuickScopedSearch.prototype, ScopedSearch.prototype);
Object.extend(QuickScopedSearch.prototype, {
	
	render: function() {
		this.resultsPanel = $(document.createElement('div'));
		this.resultsPanel.addClassName('loading');
		this.container.appendChild(this.resultsPanel);
	},
	
	reportResults: function(data) {
		
		this.dispatchEvent('onResults', this);
		
		var media = this.options.media || 'all';
		var entity = (this.options.entity && this.options.entity != 'musicTrack') ? '&entity=' + this.options.entity : '';
		
		var storeUrl = "http://ax.phobos.apple.com/WebObjects/MZStoreServices.woa/wa/search?submit=seeAllLockups&term=" + this.term + "&media=" + media + entity;
		
		var storeLink = $(document.createElement('a'));
		storeLink.setAttribute('href', storeUrl);
		storeLink.addClassName('store');
		storeLink.innerHTML = this.label;
		
		var heading = document.createElement('h3');
		heading.appendChild(storeLink);
		
		this.resultsPanel.appendChild(heading);
		
	},
	
	reportNoResults: function() {
		this.dispatchEvent('onNoResults', this);
	}
	
});

