// ==UserScript==
// @name           Jinroh BBS:G Popup
// @description    人狼BBS:Gにてアンカーをポップアップします。消すには名前をクリックしてください。
// @version        0.100312
// @include        http://www.wolfg.x0.com/*
// ==/UserScript==

var regex = /mes=all&#(\D+)(\d+)/; //
var type;                          // 発言種別。sayしかないけど。
var number;                        // レス番号
var dates;                         // 現在開いている村が何日目まで進んでいるか
var date;                          // 現在開いているログの日付（整数）
var datestr;                       // 現在開いているログの日付（文字）
var vid;                           // 現在開いている村id
var vlogstarts;                    // 各日付の開始レス番号を格納した配列。GM_setValueでキャッシュする。
var vlogurl;                       // 取得すべきレスがある日付のurl
var vlog;                          // 取得したログを一時的にキャッシュする配列

function three(int) {
	if (int < 10) {
		int = '00' + int;
	} else if (int < 100) {
		int = '0' + int;
	}
	return int;
}

function convStrToDate(datestr) {
	if (datestr.match(/(\d+)_(.+)/)) {
		var predate = RegExp.$1-0;
		var state = RegExp.$2;
		switch (state) {
			case 'ready':
				// プロローグ
				return 0;
			case 'progress':
				// 進行中
				return predate+1;
			case 'party':
				// エピローグ。
				return predate+1;
		}
	} else {
		return dates;
	}
}

function isEpilogue() {
	// このへん後でもうちょっとまともにしよう。。
	var epstr = document.getElementsByClassName('time')[0];
	if (epstr.innerHTML == 'エピローグ') {
		return true;
	}
	return false;
}

function convDateToStr(date) {
	if (date > 0) {
		//if (isEpilogue()) {
		//	return three(date)+'_party';
		//}
		date--;
		return three(date)+'_progress';
	} else {
		return '000_ready'
	}
}

function forEachTagElement(tagName, element, func) {
    var tags = element.getElementsByTagName(tagName);
    for (var i = 0; i < tags.length; i++) {
        func(tags[i]);
    }
}

// アンカーにイベントハンドラを追加する。
function scanAnchorTags(element) {
    forEachTagElement('a', element, function(tag) {
        if (regex.test(tag.href)) {
            tag.addEventListener('click', function(event) {
                clickAnchor(event, tag.href);
            }, false);
        }
    });
}

function getPageInfo() {
	var dates = document.getElementsByTagName('p')[0].getElementsByTagName('a').length;

	if (document.URL.match(/meslog=(\d+_[^&]+)/)) {
		datestr = RegExp.$1;
		vlogurl = 'meslog=' + datestr;
		date = convStrToDate(datestr);
	} else {
		date = dates;
		datestr = convDateToStr(date); // 意味は無い気がする。
		vlogurl = 'mes=all';
	}
	if (document.URL.match(/vid=(\d+)/)) {
		vid = RegExp.$1;
		vlogstarts = GM_getValue('vid'+vid);
		if (!vlogstarts) {
			vlogstarts = new Array(dates+1);
		} else {
			vlogstarts = vlogstarts.split(',');
		}
		vlog = new Array(dates+1);
	} else {
		return false;
	}
}

function initialize() {
	getPageInfo();
	scanAnchorTags(document);
}

function clickAnchor(event, href) {
	event.preventDefault();
	href = href.replace(regex, '');
	type = RegExp.$1;
	number = RegExp.$2-0;
	var logdate = date;
	var logdatestr = datestr;
	while ((vlogstarts[logdate] > number) && (logdate >= 0)) {
		logdate--;
		logdatestr = convDateToStr(logdate);
		vlogurl = 'meslog=' + logdatestr;
	}
	if (!vlog[logdate]) {
    	// 新規読み込み
		readVLog(logdate, href, vlogurl, event);
	} else {
		var html = makePopup(type, number, vlog[logdate]);
		if (html) {
			showPopup(event, html);
		}
	}

}

function readVLog(logdate, href, vlogurl, event) {
	var url = href + vlogurl;
    GM_xmlhttpRequest({
		method:"GET",
		url:url,
		onload:function(xhr) {
			vlog[logdate] = xhr.responseText.replace(/<span class="time">(\d+:\d+)/g, function(str) {
				return '<span class="time">' + logdate + 'd ' + str;
			});
			if (vlog[logdate].match(/<a name="say(\d+)">/)) {
				vlogstarts[logdate] = RegExp.$1-0;
				GM_setValue('vid'+vid, vlogstarts.toString());
			}
			if ((vlogstarts[logdate] > number) && (logdate >= 0)) {
				logdate--;
				logdatestr = convDateToStr(logdate);
				vlogurl = 'meslog=' + logdatestr;
				readVLog(logdate, href, vlogurl, event);
			} else {
				var html = makePopup(type, number, vlog[logdate], logdate);
				if (html) {
					showPopup(event, html);
				}
			}
		}
	});
}

function makePopup(type, number, html, logdate) {
	// 何度見てもひどい。
	var mesreg = new RegExp('<a name="'+type+number+'">.+\n.+\n.+\n.+\n.+\n.+\n.+\n.+\n');
	if (html.match(mesreg)) {
		html = RegExp.lastMatch;
		return html;
	} else {
		return false;
	}
}

function showPopup(event, html){
	var div = document.createElement('div');
	var offsetX = 20;
	var offsetY = 20;
	var d = document.documentElement;
	var scrollX = (window.scrollX || d.scrollLeft || document.body.scrollLeft);
	var scrollY = (window.scrollY || d.scrollTop || document.body.scrollTop);
	var windowW = (window.innerWidth || d.offsetWidth);
	var windowH = (window.innerHeight || d.offsetHeight);
	var mouseX = (navigator.userAgent.match('AppleWebKit') && (navigator.appVersion.charAt(0) < 3)) ? event.clientX - scrollX : event.clientX;
	var mouseY = (navigator.userAgent.match('AppleWebKit') && (navigator.appVersion.charAt(0) < 3)) ? event.clientY - scrollY : event.clientY;

	div.innerHTML = html;

	var s = div.style;
	s.position = 'absolute';
	s.padding = '6px 6px 0px 6px';
	s.border = '2px solid #666';
	s.textAlign = 'left';
	//s.color = 'black';
	s.backgroundColor = '#000';
	div.className = 'message';
	document.body.appendChild(div);
	var popW = div.offsetWidth;
	var popH = div.offsetHeight;
	var overX = mouseX + offsetX + popW + 30 - windowW;
	var popX = (overX < 0) ? mouseX + offsetX : (mouseX + offsetX - overX > 0) ? mouseX + offsetX - overX : 0;
	var popY = (mouseY + offsetY + popH + 8 > windowH && mouseY - offsetY - popH > 0) ? mouseY - offsetY - popH : mouseY + offsetY;
	var popL = popX + scrollX;
	var popR = popL + popW;
	var popT = popY + scrollY;
	var popD = popT + popH;
	div.style.left = popL + 'px';
	div.style.top = popT + 'px';

	// 名前をクリックして隠す。
    div.childNodes[2].addEventListener('click', function() {
        div.style.display = 'none';
    }, false);

	scanAnchorTags(div);
}

initialize();
