/*
 * Homepage L:ive Betting Static JS (using Orbis Push Server)
 */

 // ensure CVS revision number survives minification
var dummy = '$Id: hp_lb.js,v 1.1.4.3 2010-06-23 13:07:43 ndoukas Exp $';

function hp_lb_init(call_type, markets, selcns, init_msg_id, cfg) {


	//init up the array of channels we will subscribe to
	var channels = [];
	if (_hp_lb_loaded == 1) {
		return;
	}
	
	_hp_lb_loaded = 1;
	
	_hp_lb_last_msg_id = init_msg_id;


	for (var f in cfg) _hp_lb_cfg[f] = cfg[f];

	_hp_lb_store_templates();
	_hp_lb_evmkt_hash  = {};
	_hp_lb_selcn_hash  = {};

	var first_build = true;



	for (var i = 0; i < markets.length; i++) {

		scone_create(_hp_lb_evmkts_id_prefix + markets[i].ev_mkt_id, {}, null, null);
		_hp_lb_got_EVMKT(markets[i], first_build);

		if (!_hp_lb_channels["MARKET"+markets[i].ev_mkt_id]) {
			//subscribe to this market (and it's children)
			channels.push("sEVMKT" + ps_connect_lpad_id(markets[i].ev_mkt_id));
			channels.push("SEVMKT" + ps_connect_lpad_id(markets[i].ev_mkt_id));
			// add to the hash to we can't subscribe again
			// on the next ajax refresh
			_hp_lb_channels["MARKET"+markets[i].ev_mkt_id] = true;
		}


	}

	for (var i = 0; i < selcns.length; i++) {
		if (!_hp_lb_selcn_hash[selcns[i].ev_oc_id]) {
			_hp_lb_got_SELCN(selcns[i], first_build);
		}
	}

	// only register the new channels if there were any
	if (channels.length > 0) {
		ps_connect_register("hp_lb"+hp_lb_idx, _hp_lb_got_msg, channels, init_msg_id);
		hp_lb_idx++;
	}

	return;
}

/* -------- HTML TEMPLATES and ELEMENT IDs -------- */

/*
 * These are the element ids (or prefixes thereof) with special meaning.
*/

var _hp_lb_evmkts_id_prefix        = "hp_lb_evmkts_";
var _hp_lb_evmkt_id_prefix         = "hp_lb_evmkt_";

var _hp_lb_selcns_id_prefix        = "hp_lb_selcns_";
var _hp_lb_selcn_id_prefix         = "hp_lb_selcn_";

var _hp_lb_price_id_prefix         = "hp_lb_price_";

var _hp_lb_evmkt_hash  = {};
var _hp_lb_selcn_hash  = {};

var _hp_lb_price_class_name        = "odd";
var _hp_lb_price_class_name_large  = "odd-large";

/*
** Used by _hp_lb_highlight
*/
var _hp_lb_highlight_timers = {};

/*
** Hash top prevent us subscribing to channels multiple times
*/

var _hp_lb_channels = {};
var hp_lb_idx = 0;

var _hp_lb_loaded = 0;
/*
 * These are the templates used to construct and update the live betting
 * homepage page. See tmpl.js for syntax details.
 */

function _hp_lb_store_templates() {

	tmpl_store("hp_lb_evmkt", ''
	+ '<div id="hp_lb_evmkt_<%ev_mkt_id%>">\n'
	+ '		<div <%IF !bettable%>style="display:none"<%END%> id="hp_lb_selcns_<%ev_mkt_id%>"></div>\n'
	+ '		<%IF !bettable%><div class="mkt-suspended"><%XL HP_LIVE_BETTING_SUSPENDED%></div><%END%>\n'
	+ '</div>\n'
	);

	tmpl_store("hp_lb_selcn", ''
	+ '<%IF displayed == "Y"%>\n'
	+ '<div class="<%IF mkt_sort == "HH"%>odd-large<%ELSE%>odd<%END%> right nohref<%IF !bettable%> suspended<%END%>" <%IF bettable%>onclick="hp_lb_add_bet(<%ev_oc_id%>)"<%END%> id="hp_lb_selcn_<%ev_oc_id%>"><a id="hp_lb_price_<%ev_oc_id%>"  href="javascript:void(0)"><%price_str%></a></div>\n'
	+ '<%ELSE%>\n'
	+ '	<div class="<%IF mkt_sort == "HH"%>odd-large<%ELSE%>odd<%END%> right nohref" id="hp_lb_selcn_<%ev_oc_id%>"></div>\n'
	+ '<%END%>\n'
	);


}


/* ---------- PRIVATE --------- */

/* Default config items: (can be overriden by hp_lb_init call) */
var _hp_lb_cfg = {
	lang                    : "en",
	bet_threshold           : 0,
	name_truncate_threshold : 8,
	highlight_duration      : 4000,
	price_str_type          : "ODDS",
	price_str_type_ah       : "DECIMAL",
	price_str_type_hl       : "DECIMAL",
	price_str_sep           : "-"
};

/*
 * Called whenever we receive any published message from the Push Server.
 */
function _hp_lb_got_msg(msg) {

	var data = {};


	if         (msg.subject_level == "sPRICE") {
		eval("data = " +  msg.data + ";");
		data.ev_oc_id = msg.subject_id;
		_hp_lb_got_PRICE(data);
	} else if (msg.subject_level == "sSELCN") {
		eval("data = " +  msg.data + ";");
		data.ev_oc_id = msg.subject_id;
		_hp_lb_got_SELCN(data,false);
	} else if (msg.subject_level == "sEVMKT") {
		eval("data = " +  msg.data + ";");
		data.ev_mkt_id = msg.subject_id;
		_hp_lb_got_EVMKT(data,false);
	} else if (msg.subject_level == "sMHCAP") {
		eval("data = " +  msg.data + ";");
		data.ev_mkt_id = msg.subject_id;
		_hp_lb_got_MHCAP(data);
	} else {
		// presumably this msg wasn't intended for us
	}

	return;
}




function _hp_lb_got_EVMKT(data, first_build) {
	// Check if the container div exists - ignore if not.

	var containing_div = _hp_lb_evmkts_id_prefix + data.ev_mkt_id;
	var cont_el = document.getElementById(containing_div);
	if (!cont_el) {
		return;
	}

	// Determine if this is a new item and if not, make a note of
	// some of the original properties of the item. We then copy
	// fields from the message to the item's info object.

	var info = _hp_lb_evmkt_hash[data.ev_mkt_id];

	var is_new_item = !info;

	var orig_displayed;
	var orig_disporder;
	var orig_name;
	var orig_bettable;
	var orig_hcap_values;

	if (is_new_item) {
		info = data;
		_hp_lb_evmkt_hash[data.ev_mkt_id] = info;
		info.child_hash = {};
	} else {
		orig_displayed   = info.displayed;
		orig_disporder   = info.disporder;
		orig_name        = info.name;
		orig_bettable    = info.bettable;
		orig_hcap_values = info.hcap_values;
		for (var f in data) {
			info[f] = data[f];
		}
	}

	// Derive additional properties of the item.


	//console.log("bet inf run=" + info.bet_in_run);

	if (info.bet_in_run != 'Y') {
			info.displayed = "N";
	}

	info.is_new =
	  (is_new_item  && !first_build) ||
	  (!is_new_item && orig_displayed != info.displayed && info.displayed == "Y");
	info.name = info.names[_hp_lb_cfg.lang];
	info.bettable = (info.status == "A") && (info.event_status == "A");
	if (info["blurb"] == undefined) {
		info.blurb = "";
	}



	// Id of the element (and scone item) for the market.
	var scitem_id = _hp_lb_evmkt_id_prefix + data.ev_mkt_id;
	// Id of the element (and scone) holding the markets.
	var pscone_id = _hp_lb_evmkts_id_prefix + data.ev_mkt_id;

	var html = tmpl_play("hp_lb_evmkt", info);

	var sort_info = {
		disporder: info.disporder,
		ev_mkt_id: info.ev_mkt_id
	}

	var was_visible = scone_item_exists(scitem_id);
	var now_visible = false;
	if (info.displayed == "Y") {
		now_visible = true;
	}


	if (!was_visible && now_visible) {
		// add the market scone
		scone_add_item(pscone_id, scitem_id, html, sort_info);
		// Create a scone to hold the selections' HTML.
		var cscone_id = _hp_lb_selcns_id_prefix + data.ev_mkt_id;
		scone_create(cscone_id, {},_hp_lb_cmp_selcns , null);
	} else if (was_visible && now_visible) {
		scone_replace_item(scitem_id, html, sort_info, true);

	} else if (was_visible && !now_visible) {
		scone_remove_item(scitem_id);
	}



	// may need to make changes needed elsewhere.
	// Some changes require us to progagate dummy msgs for our children.
	if (now_visible && (!was_visible || orig_bettable != info.bettable)) {
		for (var ev_oc_id in info.child_hash) {
			_hp_lb_got_SELCN({
				ev_oc_id:  ev_oc_id,
				ev_mkt_id: info.ev_mkt_id
			},first_build);
		}
	}
}

function _hp_lb_got_SELCN(data, first_build) {
	// Check we've heard of the parent - ignore if not.
	// Otherwise, get info for parent and ensure he knows of us.

	var parent_info = _hp_lb_evmkt_hash[data.ev_mkt_id];

	if (!parent_info) {
		return;
	}
	parent_info.child_hash[data.ev_oc_id] = true;

	// Determine if this is a new item and if not, make a note of
	// some of the original properties of the item. We then copy
	// fields from the message to the item's info object.

	var info = _hp_lb_selcn_hash[data.ev_oc_id];
	var is_new_item = !info;

	var orig_lp_num;
	var orig_lp_den;

	if (is_new_item) {
		info = data;
		_hp_lb_selcn_hash[data.ev_oc_id] = info;
	} else {
		orig_lp_num   = info.lp_num;
		orig_lp_den   = info.lp_den;
		orig_hcap_values = info.hcap_values;
		for (var f in data) {
			info[f] = data[f];
		}
	}



	// Derive additional properties of the item.
	info.mkt_sort = parent_info.mkt_sort;
	info.name = info.names[_hp_lb_cfg.lang];
	info.name = info.name.truncate(_hp_lb_cfg.name_truncate_threshold, '...');
	if ( info.fb_result &&
	     parent_info.hcap_values ) {
		info.hcap_value = parent_info.hcap_values[info.fb_result];
	}
	info.bettable = (info.status == "A") && parent_info.bettable;

	info.price_str = hp_lb_get_price_str(
	  info.lp_num,
	  info.lp_den,
	  parent_info.lp_avail,
	  parent_info.mkt_sort
	);

	// Id of the element (and scone item) for the selection.
	var scitem_id = _hp_lb_selcn_id_prefix + info.ev_oc_id;
	// Id of the element (and scone) holding the selections.
	var pscone_id = _hp_lb_selcns_id_prefix + parent_info.ev_mkt_id;

	// If the parent is not visible, there is no need to do any display work.


	if (!scone_exists(pscone_id)) {

		return;
	}

	var html = tmpl_play("hp_lb_selcn", info);

	var sort_info = {
		disporder : info.disporder,
		lp_num    : info.lp_num,
		lp_den    : info.lp_den,
		ev_oc_id  : info.ev_oc_id
	}

	var was_visible = scone_item_exists(scitem_id);
	var now_visible = (info.displayed == "Y");

	if (!was_visible) {
		// add the selection scone
		scone_add_item(pscone_id, scitem_id, html, sort_info);
	} else if (was_visible) {
		scone_replace_item(scitem_id, html, sort_info, true);
	}
	
	// Make any changes needed elsewhere.
	if (!is_new_item && now_visible) {
		_hp_lb_highlight_price_change(
		  info.ev_oc_id, orig_lp_num, orig_lp_den, info.lp_num, info.lp_den, parent_info.mkt_sort
		);
	}
	

}

// Handle price message.
function _hp_lb_got_PRICE(data) {

	// Check we've heard of the selection and market.

	var info = _hp_lb_selcn_hash[data.ev_oc_id];
	if (!info) return;

	var parent_info = _hp_lb_evmkt_hash[info.ev_mkt_id];
	if (!parent_info) return;

	// Copy data from message to info object, making
	// a note of some original properties first.

	var orig_lp_num = info.lp_num;
	var orig_lp_den = info.lp_den;

	for (var f in data) {
		info[f] = data[f];
	}

	// The element id (and scone item id) for the selection.

	var scitem_id = _hp_lb_selcn_id_prefix + data.ev_oc_id;
	if (!scone_item_exists(scitem_id)) return;

	// Selections are sorted by price (amongst other things),
	// so we may need to reposition the selection.

	var sort_info = {
		disporder : info.disporder,
		lp_num    : info.lp_num,
		lp_den    : info.lp_den,
		ev_oc_id  : info.ev_oc_id
	};
	scone_set_item_info(scitem_id, sort_info);

	// Find where the new price needs to go.

	var price_id = _hp_lb_price_id_prefix + info.ev_oc_id;
	var price_el = document.getElementById(price_id);
	if (!price_el) return;

	// Generate new price string and store it.

	info.price_str = hp_lb_get_price_str(
	  info.lp_num,
	  info.lp_den,
	  parent_info.lp_avail,
	  parent_info.mkt_sort
	);
	price_el.innerHTML = info.price_str;

	_hp_lb_highlight_price_change(
	  info.ev_oc_id, info.lp_num, info.lp_den, orig_lp_num, orig_lp_den,parent_info.mkt_sort
	);

	return;
}

function _hp_lb_highlight_price_change(
  ev_oc_id, lp_num, lp_den, old_lp_num, old_lp_den, sort
) {

	if (isNaN(lp_num) || isNaN(old_lp_num)) return;

	var d = lp_num * old_lp_den - lp_den * old_lp_num;
	if (d == 0) return;
	var class_name = "";
	if ( sort == "HH" ) {
		class_name = _hp_lb_price_class_name_large;
	} else {
		class_name = _hp_lb_price_class_name;
	}

	var price_id = _hp_lb_selcn_id_prefix + ev_oc_id;
	_hp_lb_highlight(price_id, class_name, d);

	return;
}

/*
 * Highlight a change to an element by giving it base_class + "_d"
 * if dir is negative, or base_class + "_i" if positive, or unhighlight
 * it if dir is zero. The highlight is removed after a time interval.
 */
function _hp_lb_highlight(id, base_class, dir) {

	var el = document.getElementById(id);
	if (!el) return;

	if (dir < 0) {
		highlight_class = base_class + "_d";
	} else if (dir > 0) {
		highlight_class = base_class + "_i";
	} else {
		highlight_class = base_class+ "";
	}

	var classes = el.className.split(" ");
	var found = false;
	for (var i = 0; i < classes.length; i++) {
		if (    classes[i] == base_class + ""
		     || classes[i] == base_class + "_d"
		     || classes[i] == base_class + "_i" ) {
			classes[i] = highlight_class;
			found = true;
			break;
		}
	}
	if (!found) {
		classes.push(highlight_class);
	}
	el.className = classes.join(" ");

	if (_hp_lb_highlight_timers[id] != null) {
		window.clearTimeout(_hp_lb_highlight_timers[id]);
		delete _hp_lb_highlight_timers[id];
	}

	if (dir != 0) {
		var unhighlight_cmd =
		  "_hp_lb_highlight('" + id + "','" + base_class + "', 0)";
		_hp_lb_highlight_timers[id] =
		  window.setTimeout(unhighlight_cmd, _hp_lb_cfg.highlight_duration);
	}

	return;
}

// Handle market handicap message.
function _hp_lb_got_MHCAP(data) {

	// Get parent & item info.


	var info = _hp_lb_evmkt_hash[data.ev_mkt_id];

	if (!info) return;

	// Copy fields from the message to the item's info object.

	for (var f in data) {
		info[f] = data[f];
	}

	// Progagate handicap change to children with dummy msgs.

	for (var ev_oc_id in info.child_hash) {
		_hp_lb_got_SELCN({
			ev_oc_id:  ev_oc_id,
			ev_mkt_id: info.ev_mkt_id
		});
	}

	return;
}

// Compare two selections (for sorting within a market).
function _hp_lb_cmp_selcns(cmpMode, selcnA, selcnB) {
	var d =  selcnB.disporder - selcnA.disporder;

	if (d) return d;

	return  selcnB.ev_oc_id - selcnA.ev_oc_id;
}


// Format a price.
function hp_lb_get_price_str (
  lp_num,
  lp_den,
  lp_avail,
  mkt_sort
) {

	if (lp_avail == undefined) lp_avail = "Y";
	if (mkt_sort == undefined) mkt_sort = "--";

	var price_str_type = _hp_lb_cfg.price_str_type;

	if ( mkt_sort == "AH" && _hp_lb_cfg.price_str_type_ah != "") {
		price_str_type = _hp_lb_cfg.price_str_type_ah;
	}
	if ( mkt_sort == "HL" && _hp_lb_cfg.price_str_type_hl != "") {
		price_str_type = _hp_lb_cfg.price_str_type_hl;
	}

	if (lp_avail == "N") {
		return "SP";
	}
	if (lp_num == "" && lp_den == "") {
		return "-";
	}

	var price_str;

	if (price_str_type == "DECIMAL") {
		var dps = (lp_den > 100) ? 3 : 2;
		var dp = 1.0 + (lp_num / lp_den);
		var scaled_dp = "" + Math.round(dp * Math.pow(10,dps) - 0.5);
		var int_part  = scaled_dp.substr(0, scaled_dp.length - dps);
		var frac_part = scaled_dp.substr(scaled_dp.length - dps);
		if (int_part  == "") int_part  = "";
		if (frac_part == "") frac_part = "";
		var price_str = int_part + "." + frac_part;
	} else {
		if (lp_den == "") {
			lp_den = 1;
		}
		if (lp_num == lp_den) {
			price_str = "evens";
		} else {
			price_str = lp_num + _hp_lb_cfg.price_str_sep + lp_den;
		}
	}

	return price_str;
}










function hp_lb_add_bet(ev_oc_id) {

	var selcn = _hp_lb_selcn_hash[ev_oc_id];
	var evmkt = _hp_lb_evmkt_hash[selcn.ev_mkt_id];

	BS_set_leg("selections",  ev_oc_id);
	BS_set_leg("price_type",  "L");
	BS_set_leg("lp_num",      selcn.lp_num);
	BS_set_leg("lp_den",      selcn.lp_den);
	BS_set_leg("hcap_value",  evmkt.raw_hcap);
	BS_set_leg("bir_index",   evmkt.bir_index);
	BS_set_leg("market_tags", "");

	BS_go_bet();

	return;
}
