<script type="text/javascript" src="webui/jquery.min.js"></script>
<script type="text/javascript" src="webui/jquery.flot.min.js"></script>
<style>
.stat0 {
}
.stat1 {
}
td.bordr {
	border-right: 1px solid;
}
</style>

<div id="light" class="white_content" style="height:auto">
<div id="block_fee_stats" width="100%" style="text-align:center">

<div style="margin-top:10px">
Fee statistics for block number <b id="stat_height"></b> -
Maximum <b id="stat_max_fee"></b> SPB
&nbsp;&bull;&nbsp;
Average <b id="stat_avg_fee"></b> SPB
&nbsp;&bull;&nbsp;
Minimum <b id="stat_min_fee"></b> SPB
<span style="float:right"><a href="javascript:closepopup()">X</a>&nbsp;&nbsp;&nbsp;&nbsp;</span>
<br><br>
</div>

<div id="stat_error" class="err" style="display:none">Something went wrong (<span id="error_info"></span>)</div>
<div id="block_fees" style="height:370px;margin:5px"></div>
<br>
<div width="100%" style="margin-bottom:10px;text-align:right">
<input type="checkbox" id="block_fees_range" onchange="stat_clicked(last_hash, last_height)" checked><span onclick="block_fees_range.click()" style="cursor:pointer"> Limit range</span>
&nbsp;&bull;&nbsp;

<input type="radio" name="block_fees_mode" id="block_fees_raw" value="raw" onchange="stat_clicked(last_hash, last_height)" checked><span onclick="block_fees_raw.click()" style="cursor:pointer"> Show as is</span>
&nbsp;&bull;&nbsp;
<input type="radio" name="block_fees_mode" id="block_fees_gru" value="gru" onchange="stat_clicked(last_hash, last_height)"><span onclick="block_fees_gru.click()" style="cursor:pointer"> Try to group</span>
&nbsp;&bull;&nbsp;
<input type="radio" name="block_fees_mode" id="block_fees_spb" value="spb" onchange="stat_clicked(last_hash, last_height)"><span onclick="block_fees_spb.click()" style="cursor:pointer"> Sort by SPB</span>
</div>

</div>
</div><div id="fade" class="black_overlay"></div>

<div style="text-align:right;margin-bottom:8px;">
<input type="radio" name="stats_type" id="stats_type_min" onchange="switch_stats_type()"><span onclick="stats_type_min.click()" style="cursor:pointer"> Mining Information</span>
&nbsp;&bull;&nbsp;
<input type="radio" name="stats_type" id="stats_type_pro" onchange="switch_stats_type()"><span onclick="stats_type_pro.click()" style="cursor:pointer"> Block Processing</span>
</div>
<table class="blocks bord" id="blkstab">
<tr>
	<th colspan="7">Block info
	<th class="stat0" colspan="4">Mining Information
	<th class="stat1" colspan="7">Block Processing <i>(ms)</i>
<tr>
	<th width="52">Height
	<th width="70" id="ts_rcvd_lab" onclick="swap_time_mode()" style="cursor:pointer">Received
	<th width="480">Hash
	<th width="35" align="right">TXs
	<th width="40" align="right">SiOps
	<th width="45" align="right">kByte
	<th>
	<th class="stat0" width="30">BTC
	<th class="stat0" width="30" align="right">SPB
	<th class="stat0" width="20">Ver
	<th class="stat0 bordr" align="left">Miner
	<th class="stat1" width="10" title="Received from ConnID">Fro
	<th class="stat1" width="10" title="Missing TXs in cmpctblk">Mis
	<th class="stat1" width="20" title="Preprocessing time ms" align="right">Pre
	<th class="stat1" width="20" title="Full download time ms" align="right">D/L
	<th class="stat1" width="20" title="Queueing time ms" align="right">Que
	<th class="stat1" width="20" title="Block committed after ms" align="right">Ver
	<th class="stat1" width="10" title="Extra times received">X
</tr>
</table>
<br>
Block Version Legend:<br>
&bull; <b>+</b> - Supports 2MB blocks (BIP-109)<br>
&bull; <b>U</b> - Signals BU's <span class="mono">/EBx/ADy/</span> thingy  <span id="ebad_cnt"></span><br>
&bull; <b>1,2,3,4</b> - Old fasion blocks (before BIP9)<br>
&bull; <b>?</b> - Unrecognized block version<br>
<script>
function switch_stats_type() {
	if (stats_type_pro.checked) {
		css('.stat1', 'display', 'table-cell')
		css('.stat0', 'display', 'none')
		localStorage.setItem("blocks_info", "pro")
	} else {
		css('.stat0', 'display', 'table-cell')
		css('.stat1', 'display', 'none')
		localStorage.setItem("blocks_info", "min")
	}
}
function remember_info_setting() {
	var mod = localStorage.getItem("blocks_info")
	if ((mod+'').length!=3) mod = "min"
	document.getElementById('stats_type_'+mod).checked = true
}
remember_info_setting()
switch_stats_type()

const MINER_ID_COLUMN = 10

var show_timestamp = false

function swap_time_mode() {
	show_timestamp = !show_timestamp
	ts_rcvd_lab.innerText = show_timestamp ? 'T.stamp' : 'Received'
	refreshblocks()
}

var mid = null

function hlminer(i) {
	var row = blkstab.rows[2+i]
	mid = row.cells[MINER_ID_COLUMN].innerHTML
	if (row.className.indexOf("own")!=-1) {
		mid = null
	}
	for (var i=2; i<blkstab.rows.length; i++) {
		if (blkstab.rows[i].cells[MINER_ID_COLUMN].innerHTML==mid) {
			blkstab.rows[i].classList.add("own")
		} else {
			blkstab.rows[i].classList.remove("own")
		}
	}
}


function do_rcvd_time(td) {
	td.innerText = ((time_now-parseInt(td.name))/60.0).toFixed(1) + 'min'
}


function ms2str(v) {
	if (v>=10e3) {
		if (v>=180e3) {
			if (v>=3600e3) {
				v = (v/3600e3).toFixed(1) + 'hrs'
			} else {
				v = (v/60e3).toFixed(1) + 'min'
			}
		} else {
			v = (v/1000).toFixed(1) + 's'
		}
	}
	return v
}


var last_hash, last_height
var prvpos = null

function stat_clicked(hash, height) {
	var aj = ajax()
	last_hash = hash
	last_height = height
	aj.onreadystatechange=function() {
		if(aj.readyState==4) {
			if (prvpos==null) {
				fade.addEventListener('click', closepopup)
				fade.style.cursor = 'pointer'
				fade.title = 'Click here to close the popup'
			}

			prvpos = document.body.scrollTop
			window.scrollTo(0,0)

			light.style.display='block'
			fade.style.display='block'
			document.addEventListener("scroll", noscroll)


			try {
				var stats = JSON.parse(aj.responseText)

				// hide error message
				stat_error.style.display = 'none'

				if (block_fees_gru.checked) {
					var stat2 = new Array()
					var curr_elem = [0,0,0]
					for (var i=0; i<stats.length; i++) {
						if (stats[i][2]!=curr_elem[2]) {
							if (curr_elem[0] > 0) {
								stat2.push(curr_elem)
							}
							curr_elem = [0,0,stats[i][2]]
						}
						curr_elem[0] += stats[i][0]
						curr_elem[1] += stats[i][1]
					}
					if (curr_elem[0] > 0) {
						stat2.push(curr_elem)
					}
					stats = stat2
				} else if (block_fees_spb.checked) {
					stats.sort(function (a, b) {
						var spb_a = a[1] / a[0]
						var spb_b = b[1] / b[0]
						return ( spb_a < spb_b ) ? 1 : ( (spb_a != spb_b) ? -1 : 0 )
					})
				}

				var plot_data = [ { data : [], points: { show:false }, lines: {show:true, fill:true}} ];

				var plot_options = {
					xaxis: { max : 1e6,  position : "top", tickSize:100e3, alignTicksWithAxis: 200,
						tickFormatter : function(a) {return (a/10e3) + "%"} },
					yaxis : { position : "right",
						tickFormatter : function(a) {return a + " SPB"},
						labelWidth : 80 }
				}

				var max_spb, min_spb, spb
				var totbytes = 0
				var totfees = 0
				for (var i=0; i<stats.length; i++) {
					spb = stats[i][1] / stats[i][0]
					if (i==0) {
						max_spb = min_spb = spb
					} else {
						if (spb>max_spb) max_spb=spb
						else if (spb<min_spb) min_spb=spb
					}

					totbytes += stats[i][0]
					totfees += stats[i][1]
					plot_data[0].data.push([totbytes, spb])
				}

				var avg_fee = totfees / totbytes
				stat_max_fee.innerText = max_spb.toFixed(0)
				stat_avg_fee.innerText = avg_fee.toFixed(1)
				stat_min_fee.innerText = min_spb.toFixed(2)

				if (block_fees_range.checked) {
					plot_options.yaxis.max = (avg_fee > 33) ? 3 * avg_fee : 100
				}

				$.plot($("#block_fees"), plot_data, plot_options)


			} catch (e) {
				console.log(e)
				error_info.innertText = aj.responseText
				stat_error.style.display = 'block'
			}

			stat_height.innerText = height
			//stat_hash.innerText = hash

		}
	}
	aj.open("GET","blfees.json?height="+height, true);
	aj.send(null);
}

function refreshblocks() {
	function onc_mid(c,id) {
		c.onclick = function() {hlminer(id)}
	}

	function onc_stat(c,hash,height) {
		c.onclick = function() {stat_clicked(hash, height); return false}
	}

	var aj = ajax()
	aj.onerror=function() {
		setTimeout(refreshblocks, 1000)
	}
	aj.onload=function() {
		try {
			var cs = JSON.parse(aj.responseText)
			var ebad_c = 0

			while (blkstab.rows.length>2) blkstab.deleteRow(2)

			for (var i=0; i<cs.length; i++) {
				var td, row = blkstab.insertRow(-1)

				row.className = 'hov'
				row.title = "Rcvd at " + tim2str(cs[i].Received) + " with TS " + tim2str(cs[i].Timestamp)

				td = row.insertCell(-1)
				td.className = 'bold'
				td.style.textAlign = 'center'
				td.innerText = cs[i].Height

				td = row.insertCell(-1)
				td.style.textAlign = 'right'
				td.className = 'i'
				td.name = cs[i].Received
				if (show_timestamp) {
					td.innerText = tim2str(cs[i].Timestamp, true)
				} else {
					do_rcvd_time(td)
				}

				td = row.insertCell(-1)
				td.className = 'mono block_hash nw'
				td.innerText = cs[i].Hash
				//var h = cs[i].Hash
				if (cs[i].HaveFeeStats) {
					var img = document.createElement('img')
					img.src = 'webui/stats.png'
					img.className = 'hand'
					img.style.margin = '0px 0px 0px 10px'
					td.appendChild(img)
					onc_stat(img, cs[i].Hash, cs[i].Height)
					//h += '<img src="webui/stats.png" style="float:right" onclick="feestats(\'' + h + '\')">'
				}

				td = row.insertCell(-1)
				td.style.textAlign = 'right'
				if (cs[i].TxCnt>1)  td.innerText = cs[i].TxCnt

				td = row.insertCell(-1)
				td.style.textAlign = 'right'
				td.className = 'blsigops'
				if (cs[i].Sigops>0)  td.innerText = cs[i].Sigops

				td = row.insertCell(-1)
				td.style.textAlign = 'right'
				td.className = 'bold'
				td.innerText = (cs[i].Size/1000.0).toFixed(1)
				if (cs[i].NonWitnessSize>0 && cs[i].NonWitnessSize!=cs[i].Size) {
					td.style.color = 'blue'
					td.title = cs[i].Size + ' -> ' + cs[i].NonWitnessSize
					//(cs[i].NonWitnessSize/1000.0).toFixed(1)
				}
				td = row.insertCell(-1)
				td.innerText = ''

				td = row.insertCell(-1)
				td.className = 'blreward stat0'
				td.innerText = (cs[i].Reward/1e8).toFixed(2)

				td = row.insertCell(-1)
				td.className = 'blspb stat0'
				td.innerText = cs[i].FeeSPB.toFixed(1)

				td = row.insertCell(-1)
				td.style.textAlign = 'center'
				td.className = 'stat0'
				var vx = ''
				if (cs[i].Version<=4) {
					vx = cs[i].Version
				} else {
					if (cs[i].Version&0x20000000) {
						if (cs[i].Version&0x10000000) {
							vx += '+'
						}
					} else {
						vx = '?'
					}
				}
				if (typeof(cs[i].EBAD)=="string" && cs[i].EBAD!="") {
					ebad_c++
					vx += 'U'
				}
				td.innerText = vx
				td.title = '0x' + cs[i].Version.toString(16) + cs[i].EBAD

				var miner = cs[i].Miner.substr(0,11)
				td = row.insertCell(-1)
				td.className = "i stat0 hand bordr"
				td.innerText = miner
				onc_mid(td, i)

				td = row.insertCell(-1)
				td.style.textAlign = 'right'
				td.className = 'nodeid stat1'
				if (cs[i].TimeVer>0)  td.innerText = cs[i].FromConID

				td = row.insertCell(-1)
				td.style.textAlign = 'right'
				td.className = 'blstatmissedtxs stat1'
				if (cs[i].MissedCnt>0)  td.innerText = cs[i].MissedCnt

				td = row.insertCell(-1)
				td.style.textAlign = 'right'
				td.className = 'blstat stat1'
				var time_base = cs[i].TimePre
				if (cs[i].TimePre>0)  td.innerText = cs[i].TimePre

				td = row.insertCell(-1)
				td.style.textAlign = 'right'
				td.className = 'blstat stat1'
				if (cs[i].TimeDl>0) {
					td.innerText = ms2str(cs[i].TimeDl - time_base)
					time_base = cs[i].TimeDl
				}

				td = row.insertCell(-1)
				td.style.textAlign = 'right'
				td.className = 'blstat stat1'
				if (cs[i].TimeQue>0) {
					td.innerText = ms2str(cs[i].TimeQue - time_base)
					time_base = cs[i].TimeQue
				}

				td = row.insertCell(-1)
				td.style.textAlign = 'right'
				td.className = 'blstat stat1'
				if (cs[i].TimeVer>0) {
					td.innerText = ms2str(cs[i].TimeVer - time_base)
				}

				td = row.insertCell(-1)
				td.style.textAlign = 'right'
				td.className = 'blstatwaste stat1'
				if (cs[i].WasteCnt>0)  td.innerText = cs[i].WasteCnt

				if (cs[i].TimeVer>=0) { // block received during this uptime
					if (cs[i].MissedCnt>=0) {
						row.classList.add("bip152")
					} else {
						if (cs[i].MissedCnt==-2) {
							row.classList.add("CFN") // Cornell-Falcon-Network
						}
					}
				}
			}

			ebad_cnt.innerText = '(' + ebad_c + '/' + cs.length + ')'

			if (mid!=null) {
				for (var i=2; i<blkstab.rows.length; i++) {
					if (blkstab.rows[i].cells[7].innerHTML==mid) {
						blkstab.rows[i].classList.add("own")
					}
				}
			}
		} catch(e) {
			console.log(e)
		}
	}
	aj.open("GET","blocks.json",true)
	aj.send(null)
}



var _lblo = 0

blno.addEventListener("lastblock", function(e) {
	if (e.block.Height!=_lblo) {
		_lblo = e.block.Height
		refreshblocks() // refersh the table for each new block notifiaction
	} else if (!show_timestamp) {
		for (var i=2; i<blkstab.rows.length; i++) {
			do_rcvd_time(blkstab.rows[i].cells[1])
		}
	}
})

document.addEventListener('DOMContentLoaded', function() {
	window.onkeyup = function (event) {
		if(event.keyCode == 27)  closepopup()
	}
})

</script>
