// deals with general interactions with the pitch
var PitchEngine = Class.create(
{
	
  initialize : function() {
    this.players = new Array();
		this.pitch = $('player_map');
		this.vis_selector = $('displayed-players');
		this.static_player_list = $('players-list');
		
		this.admin_mode = false;
		
		this.configure_pitch();

		// may be able to admin the players straight away
		if (has_right('profile_admin'))
			this.adminise_players();

    // after they login we may need to make everything adminable
    Event.observe(document, 'session:logged_in', function(e){
			if (has_right('profile_admin'))
				this.adminise_players();
    }.bind(this));

		// deal with player requests being accepted
		Event.observe(document, 'request:accept_team_player', function(e){
			var result = e.memo;
			if (result.success) {
				var new_player = {
					  actor_id : result.player_position.player_id
					, name     : result.name
					, url      : '/members/' + result.alias
					, top      : result.player_position.pos_top
					, left     : result.player_position.pos_left
				};
				this.add_player(new_player);
			}
		}.bind(this));
  },

	configure_pitch : function() {
		// make the pitch into a dropable prototype container
	  Droppables.add('player_map', { 
	    accept: 'little-player',
	    onDrop: function(elm) { 
	      // find the player that was dragged - and let it know
				this.players.each(function(player){
					if (player.player_real == elm) {
						// notify the player so it can update and redraw in the new position
						player.notify_dropped();
						
						// either save or update the request form
						if (player.is_self)
							this.update_request_form(player);
						else
							this.save_player(player);
					}
				}.bind(this));
	    }.bind(this)
	  });
	},

	add_player : function(player) {
		// create the new player and add to the pitch
		var new_player = new Player(this, player);
		this.players.push(new_player);
		
		// if running in admin mode we make the player adminable straight away
		if (this.admin_mode)
			new_player.make_adminable();
		
		return new_player;
	},
	
	adminise_players : function() {
		this.admin_mode = true;
		
		// make all the players on the pitch adminable
		this.players.each(function(player){ player.make_adminable(); });
	},
	
	add_own_player : function() {
		// they need to be logged in to do this
	  if (!logged_in()) {
	    request_login(this.add_own_player.bind(this));
	    return false;
	  }
		
		// now we should be able to grab their member details
		var actor = member_actor();
		var player = { actor_id : actor.actor_id, name:actor.name, url:actor.url, left:160, top:230 };
		
		// make sure the player isn't already on the pitch
		if (this.players.any(function(p){ return p.player.actor_id == actor.actor_id; })) {
			display_notification('You are already playing on this team. If you are not visible it is because the administrators have decided to hide your player.');
			return false;
		}
		
		// adds a player for the logged in member
		var new_player = new Player(this, player);
		this.players.push(new_player);
		new_player.make_self();
		
		// update the form straight away (so the general values are set)
		this.update_request_form(new_player);

		// show the request form
		new Effect.BlindDown('play-in-team-form', {duration:.3});
		$('call-to-add-self').hide();

		return new_player;
	},
	
	
	update_request_form : function(player) {
		// update the request form with the new player position
		$('player_position_pos_top').value = player.player.top;
		$('player_position_pos_left').value = player.player.left;
		$('player_position_player_id').value = player.player.actor_id;
	},

	save_player : function(player) {
	  var url = context_url + '/team_player/player_save/' + player.player.actor_id.toString() + '.json';
		var params = 'pos_top=' + player.player.top + '&pos_left=' + player.player.left + '&is_displayed=' + player.player.visible;

	  // save the details
	  var request = new Ajax.Request(url,
	  {
	    asynchronous  : true, 
	    parameters    : params, 
	    onFailure     : function(t) { display_notification('Couldn\'t update the player information.'); }
	  });
	}

});




// represents a single player in the team (visible on the pitch or not)
var Player = Class.create(
{

  initialize : function(engine, player) {
		// ref to the PitchEngine
		this.engine = engine;
		// ref to the player div on the pitch
		this.player_real = null;

		// can this player be moved around
		this.mobile =  false;
		// is this their own player
		this.is_self = false;
		
    this.player = {
			  left     : 0
			, top      : 0
			, visible  : true
			, name     : ''
			, url      : ''
			, actor_id : 0
    };
    Object.extend(this.player, player || { });

		this.redraw();
  },

	make_adminable : function() {
		// make it so that the player can be moved and auto-saves
		this.make_mobile();
	},

	make_self : function() {
		// make it so that the player can be moved and auto-updates the player request form
		this.is_self = true;
		this.make_mobile();
	},
	
	make_mobile : function() {
		// make it so that the player can be moved
		if (!this.mobile) {
			this.mobile = true;
			this.attach_drag();
		}
	},

	notify_dropped : function() {
		// this player has been moved about the pitch
		
		// update the position
    var drop_pos = this.drag_ref.currentDelta();
    var top = drop_pos[1];
    var left = drop_pos[0];
		this.update_position(top, left);
		
		// redraw it with the new position
		this.redraw();
	},

	update_position : function(top, left) {
		// change the position of the player
		this.player.top = top;
		this.player.left = left;
		this.redraw();
	},
	
	update_visibility : function(visible) {
		this.player.visible = visible;
		this.redraw();
	},


	redraw : function() {
		// redraw the player on the pitch (and in the admin selector)

		// kill the old player (if it exists)
		if (this.player_real)
			this.kill_old_player();

	  // create the new player
	  var player = new Element("div");
	  player.addClassName('little-player');
	  player.setStyle({position:'absolute', top:this.player.top.toString()+'px', left:this.player.left.toString()+'px'});
	  player.insert(new Element("div", {className:'player_name'}).update('<a href="'+this.player.url+'">' + this.player.name + '</a>'));
	  player.insert(new Element("div", {className:'png-fix', style:'background:url(/images/elements/players/player_f.png) 0 0 no-repeat; width:47px; height:48px;'}));

		this.player_real = player;
		this.engine.pitch.insert(this.player_real);

		// player may not actually be visible
		if (!this.player.visible)
			this.player_real.hide();
			
	  // may need to be able to drag it around
		if (this.mobile) {
			this.attach_drag();
		}
		
		if (!this.select_option) {
			this.select_option = new Option(this.player.name, this.player.actor_id.toString());
			try {
			  this.engine.vis_selector.add(this.select_option, null); // doesn't work in IE
			} catch(e) {
			  this.engine.vis_selector.add(this.select_option); // works in IE
			}
			Event.observe(this.engine.vis_selector, 'change', this.select_changed.bind(this))
		}
		this.select_option.selected = this.player.visible;
	},
	
	select_changed : function() {
		// the admin selection has changed (may need to show/hide stuff - and resave)
		if (this.select_option.selected != this.player.visible) {
			this.update_visibility(this.select_option.selected);
			this.engine.save_player(this);
		}
	},
	
	kill_old_player : function() {
		if (this.mobile && this.drag_ref)
			this.drag_ref.destroy();

		// remove from the pitch
		this.player_real.remove();
		this.player_real = null;
	},
	
	attach_drag : function() {
		this.drag_ref = new Draggable(this.player_real, { revert:true });
	}
	
});

