/*
 * Classe player: usa o DOM para reconhecer uma lista (listID) que controla o conteúdo (ID_content) de acordo com o item (li) atualmente selecionado na lista.
 *
 * Para usar a classe, você deve passar por parâmetro a opção loader, que é uma função que lê os dados e obrigatoriamente deve disparar o evento contentLoad juntamente com a opção id_div (fireEvent('contentLoad', id_iv)). A função ainda deve estabelecer o new_content da classe. A função loader recebe ainda, como parâmetro, o conteúdo do link clicado e a id_div
 *
 * @todo 1 - talvez o getElements(div) possa ser simplesmente alterado para getElements()
 * @todo 2 - não seria melhor simplesmente passar o new_content por parâmetro?
 * @todo 3 - o novo ID a ser usado na nova div é passada por parâmetro pela função externa. Tentar definir isso dentro da própria classe
 *
*/

var Player = new Class({
	Implements: [Options, Events],

	options: {
		loading_label:		true,			// Define se dever-se-á inserir um layer loading na frente do conteúdo
		sel_index:			0,				// O índice numérico do Li selecionado
		loader: $empty,						// Define a função EXTERNA encarregada de capturar o novo conteúdo
		onContentLoad:		function(id_div){
			this.addLoadedContent(id_div);
		},
		timeout: 10000,						// Quanto tempo depois será verificado se o conteúdo foi carregado
		nextClick: 300						// Define quanto tempo depois se poderá fazer nova solicitação
	},

	// status: define status temporários internos da classe, que não devem ser alterados pelo usuário
	status: {
		used_id: 0,							// O número que identifica exclusivamente a div content criada
		sel_index: 0,						// O índice numérico do Li selecionado
		content_loaded: Array,				// Indica se o conteúdo novo daquele ID já foi carregado
		loading_added: false,				// Indica se o layer loading já foi inserido
		verificaContNovo: null,						// Função programada por delay para verificar se o conteúdo foi carregado
		canClick: true
	},

	// initialize: instancia a classe, atribuindo o container this.container e as opções dadas pelo usuário
	// STATUS:
	// 			this.ul fica aberto, gastando memória
	// 			this.li fica aberto, gastando memória
	initialize: function(container, options){
		this.setOptions(options);
		if(options){
			if(options.loader){
				this.options.loader	= this.options.loader.bind(this);	// bind a função externa para que ela altere a instância
			}
		}
		this.status.sel_index	= this.options.sel_index;
		delete(this.options.sel_index);
		this.container	= container;						// Apenas o ID do container
		this.ul			= $(this.container+'_list');
		this.li			= this.ul.getElements('li');
		// Atribui as funções aos cliques nos links
		this.li.each(function(list, key){
			var link	= list.getElement('a');
			link.addEvent('click', function(event){
				/*var temp		= link.href;
				link.href		= 'javascript:;';
				link.href2		= temp;*/
				this.startChange(key);
				event.preventDefault();
				/*link.href		= temp;
				link.erase('href2');
				delete(temp);*/
				return false;
			}.bind(this))
		}.bind(this))
	},


	/*
	
	!!!!!!!!!!!!!! AS DUAS funções ABAIXO DEVEM, POSTERIORMENTE, SER REMOVIDAS E EM SEU LUGAR DEVE-SE USAR CLASSE EXTERNA
	
	*/
	hide: function(el, callback){
		var trans		= new Fx.Tween(el, {duration: 500});
		trans.start('opacity', 0);
		trans.addEvent('complete', function(el){
			el.destroy();
			if(callback){
				callback();
			}
		}.bind(this))
	},

	show: function(el, callback){
		var trans		= new Fx.Tween(el, {duration: 500});
		trans.set('opacity', 0);
		el.inject(this.content_container);
		trans.start('opacity', 1);
		if(callback){
			trans.addEvent('complete', function(){
				callback();
			})
		}
	},
	/*
	
	END !!!!!!!!!!!!!!
	
	*/

	// selector altera o seletor atual, tira a classe .selected do anteriormente selecionado e a atribui ao novo Li selected
	// STATUS: OK - como está no começo do processo, a tendência é ser rápido e mesmo com muitos cliques não há problemas
	/* 1 */selector: function(key){
		this.li[this.status.sel_index].getElement('a').removeClass('selected');
		this.li[key].getElement('a').addClass('selected');
		this.status.sel_index		= key;
	},

	// Carrega conteúdo da nova div
	/* 2 */load_new: function(key, id_div){
		/*this.options.loader.delay(400, null, this.li[key].getElement('a').href);*/
		this.options.loader(this.li[key].getElement('a').href, id_div);
		this.status.verificaContNovo = this.confer_new.delay(this.options.timeout, this, id_div);
	},

	// Verifica se houve resposta do servidor
	// STATUS: observe-se que, se após o timeout o conteúdo for carregado, então haverá a recriação da div do conteúdo
	confer_new: function(id_div){
		// Não houve resposta do servidor, o conteúdo não foi carregado
		if(this.status.content_loaded[id_div] == false){
			this.new_content		= new Element('div', {text: "Erro ao carregar"});
			this.fireEvent('contentLoad', id_div);
		}
	},

	// Remove a div com o conteúdo antigo
	/* 3 */remove_old: function(id_div){
		this.content_container_div	= this.content_container.getElement('#'+this.container+'_cont_'+id_div);	// A div interna da div com o conteúdo
		
		// Verifica se a div ainda existe, útil para usuários que clicam avidamente sobrepondo as tarefas.
		if(this.content_container_div){
			var contWidth				= this.content_container_div.getSize().x;
			this.content_container_div.setStyle('width', contWidth);
			this.content_container_div.setStyle('position', 'absolute');
			delete(contWidth);
			this.hide(this.content_container_div, this.add_loading.bind(this));
			delete(this.content_container_div);
		}
		else {
			this.remove_old.delay(100, this, id_div);
		}
	},

	// Adiciona a div com o layer loading
	add_loading: function(){
		if(this.options.loading_label == true && this.status.content_loaded[this.status.used_id] != true){
			this.layer		= new Layer(this.container+'_content', {layer: true});
			this.layer.inject();
			this.status.loading_added	= true;
		}
	},

	// Remove a div Layer loading
	remove_loading: function(){
		if(this.options.loading_label == true && this.status.loading_added == true){
			this.layer.destroy();
			this.status.loading_added	= false;
		}
	},

	/**
	 * Adiciona a div de ID id_div com o conteúdo novo dentro do player
	 */
	addLoadedContent: function(id_div){ // @todo 3
		this.remove_loading();
		// @todo 1 - A condicional abaixo serve para consertar eventuais erros, causados principalmente por múltiplos cliques
		var contents		= $(this.container+'_content').getElements('div');
		delete(contents[0]);	// desconsidera o primeiro div existente. Não vai deletá-lo agora, para efeitos de animação
		if(contents){
			$each(contents, function(el){
				el.destroy();
			})
		};
		delete(contents);
		// END condicional

		// @todo 2
		var div				= new Element('div', {'id': this.container+'_cont_'+id_div, 'class': 'player_content'});
		this.new_content.inject(div);
		this.new_content	= div;
		this.show(this.new_content, this.cursorToWaiting.bind(this));

		// adapta o tamanho da div content
		var contHeight	= this.new_content.getSize().y;
		var trans		= new Fx.Tween(this.content_container, {duration: 500, link: 'cancel'});
		trans.start('height', contHeight);
		trans.addEvent('complete', function(){
			this.content_container.setStyle('height', 'auto');
		}.bind(this));
		delete(contHeight);
		delete(trans);
	},


	/////////////////////////////////////////////////////////
	// Inicia a substituição do conteúdo antigo pelo novo
	startChange: function(key){
		if (this.status.canClick == false) return false;
		this.status.canClick					= false;
		
		// Zera/atualiza os status
		this.status.used_id++;
		var id_div			= this.status.used_id;
		(function(){this.status.canClick = true}).delay(200, this);

		this.status.content_loaded[id_div]		= false;
		$clear(this.status.verificaContNovo);	// Apaga o timer anterior que dispara a verificação de carregamento do conteúdo
		// 1 - Altera o link selecionado e muda o cursor do mouse
		this.selector(key);
		$$('*').setStyle('cursor', 'wait');

		this.content_container	= $(this.container+'_content');				// A div com o conteúdo

		// 2 - Carrega conteúdo da nova div
		this.load_new(key, id_div);

		// 3 - Seta o tamanho da div do conteúdo antigo e a remove
		var contHeight	= this.content_container.getSize().y;
		this.content_container.setStyle('height', contHeight);
		delete(contHeight);
		this.remove_old(id_div.toInt()-1);
	},

	cursorToWaiting: function(){		
		$$('*').setStyle('cursor', 'default');
		$$('*').setStyle('cursor', '');
		// Libera memória
		
	}
	//
	/////////////////////////////////////////////////////////

})
