/**************************************************
 * Konata☆Chat for FF Adventure Next
 * Copyright (C) 2007-2008 Akkima
 *
 * http://ffa.x0.to/
 **************************************************/

var CHARACTER_NAME;

// 発言の種類
var CHAT_TYPE_ALL     = 0;	// 全体
var CHAT_TYPE_WIS     = 1;	// 耳打ち
var CHAT_TYPE_PARTY   = 2;	// パーティ
var CHAT_TYPE_GUILD   = 3;	// ギルド
var CHAT_TYPE_SYSTEM  = 4;	// システムメッセージ
var CHAT_TYPE_ADMIN   = 5;	// 天の声
var CHAT_TYPE_SYSTEM2 = 6;	// 名前なしシステム (ヘルプ等用)

// フィルター用ビット設定
var CHAT_FILTER_ALL    = 0x01;	// 全体
var CHAT_FILTER_WIS    = 0x02;	// 耳打ち
var CHAT_FILTER_PARTY  = 0x04;	// パーティ
var CHAT_FILTER_GUILD  = 0x08;	// ギルド
var CHAT_FILTER_SYSTEM = 0x10;	// システムメッセージ
var CHAT_FILTER_ADMIN  = 0x20;	// 天の声

var CHAT_FILTER_ENABLE_ALL = (CHAT_FILTER_ALL | CHAT_FILTER_WIS | CHAT_FILTER_PARTY | CHAT_FILTER_GUILD | CHAT_FILTER_SYSTEM | CHAT_FILTER_ADMIN);

var g_iSendType = CHAT_TYPE_ALL;	// 現在設定されている発言の種類
var g_iWisName  = "";				// 現在設定されている1:1送信先

var typeArray = new Array(
	'All',
	'-',
	'<span class="ft1">Party</span>',
	'-',
	'-',
	'-'
);

var ChatLog = function (arg)
{
	var aSplited = arg.split("\t");
	this.iNumber = aSplited[0];
	this.strID = aSplited[1];
	this.strName = aSplited[2];
	this.strWisName = aSplited[3];
	this.strMessage = aSplited[4];
	this.strTime = aSplited[5];
	this.iType = aSplited[6];

	return this.iNumber;
};

// チャットを表示
ChatLog.prototype.render = function ()
{
	var objChatFrame = $("chatframe");
	var strAdd = "";

	if (this.iType == CHAT_TYPE_ADMIN) {
		strAdd += "<span class=\"ft0\">";
	} else if (this.iType == CHAT_TYPE_PARTY) {
		strAdd += "<span class=\"ft1\">";
	} else if (this.iType == CHAT_TYPE_SYSTEM || this.iType == CHAT_TYPE_SYSTEM2) {
		strAdd += "<span class=\"ft2\">";
	} else if (this.iType == CHAT_TYPE_WIS) {
		strAdd += "<span class=\"ft3\">";
	} else {
		strAdd += "<span>";
	}

	// 本文とか
	if (this.iType != CHAT_TYPE_SYSTEM2) {
		if (this.iType == CHAT_TYPE_WIS) {
			if (this.strName == CHARACTER_NAME) { // to
				strAdd += "[to " + this.strWisName + "]";
			} else { // from 
				strAdd += "[from " + this.strName + "]";
			}
		} else {
			strAdd += this.strName;
		}
		strAdd += " &gt; " + this.strMessage + " [" + this.strTime + "] ";
	} else {
		strAdd += this.strMessage;
	}

	// 識別子とか
	strAdd += "</span>";

	if (this.strID != 0 && this.strName != CHARACTER_NAME) {
		strAdd += " [<a href=\"./\" onclick=\"sendChatString('/wis " + this.strName + "'); return false;\" title=\"/wis " + this.strName + "\">W</a>]" + 
				  " [<a href=\"./\" onclick=\"changeSubWindow(); sendChatString('/mail " + this.strName + "'); return false;\" title=\"/mail " + this.strName + "\">M</a>]";
	}

	strAdd += "<br />";

	objChatFrame.innerHTML += strAdd;
}

var Chat = function ()
{
	this.iNewestNumber = -1;
	this.iCurrentNumber = -1;
	this.iLength = 0;
	this.iFilter = CHAT_FILTER_ENABLE_ALL;
	this.aChatLog = new Array();
}

Chat.prototype.clear = function ()
{
	delete this.aChatLog;

	this.iCurrentNumber = -1;
	this.iLength = 0;
	this.aChatLog = new Array();

	$("chatframe").innerHTML = "";
}

Chat.prototype.setFilter = function (iFilter)
{
	this.iFilter = iFilter;
	this.render();
}

Chat.prototype.addChatLog = function (strNew)
{
	// 追加する要素が何もない
	if (strNew == "" || strNew == "\n") {
		return false;
	}

	this.iCurrentNumber++;
	this.iCurrentNumber %= MAX_CHAT_BUFFER;

	// バッファーが最大だった場合、一番古いものを削除
	if (this.iLength == MAX_CHAT_BUFFER) {
		delete this.aChatLog[this.iCurrentNumber];
	} else {
		this.iLength++;
	}

	// 新たにオブジェクトを作成
	this.aChatLog[this.iCurrentNumber] = new ChatLog(strNew);
	if (this.aChatLog[this.iCurrentNumber].iNumber != 0) {
		this.iNewestNumber = this.aChatLog[this.iCurrentNumber].iNumber;
	}
}

Chat.prototype.add = function (strNew)
{
	// 1行ごとに処理する
	var aSplited = strNew.split("\n");
	var i;

	for (i = 0; i < aSplited.length; i++) {
		this.addChatLog(aSplited[i]);
	}
}

Chat.prototype.render = function ()
{
	if (this.iLength == 0) {
		return false;
	}

	$("chatframe").innerHTML = ' ';

	var iCount = this.iCurrentNumber;				   // 開始位置
	var iEnd = (this.iCurrentNumber - this.iLength);	// 終了位置
	if (iEnd < 0) {
		iEnd += MAX_CHAT_BUFFER;
	}

	while (1) {
		// 描画
		var bFlag = false;

		// フィルタ関連
		if (this.aChatLog[iCount].iType == CHAT_TYPE_ALL) {
			if (this.iFilter & CHAT_FILTER_ALL) { bFlag = true; }
		} else if (this.aChatLog[iCount].iType == CHAT_TYPE_WIS) {
			if (this.iFilter & CHAT_FILTER_WIS) { bFlag = true; }
		} else if (this.aChatLog[iCount].iType == CHAT_TYPE_PARTY) {
			if (this.iFilter & CHAT_FILTER_PARTY) { bFlag = true; }
		} else if (this.aChatLog[iCount].iType == CHAT_TYPE_GUILD) {
			if (this.iFilter & CHAT_FILTER_GUILD) { bFlag = true; }
		} else if (this.aChatLog[iCount].iType == CHAT_TYPE_SYSTEM ||
					this.aChatLog[iCount].iType == CHAT_TYPE_SYSTEM2) {
			if (this.iFilter & CHAT_FILTER_SYSTEM) { bFlag = true; }
		} else if (this.aChatLog[iCount].iType == CHAT_TYPE_ADMIN) {
			if (this.iFilter & CHAT_FILTER_ADMIN) { bFlag = true; }
		} else {
			bFlag = true;
		}

		if (bFlag) {
			this.aChatLog[iCount].render();
		}

		// 次に進める
		iCount--;
		if (iCount < 0) {
			iCount += MAX_CHAT_BUFFER;
		}

		// 最後まで回ったら抜ける
		if (iCount == iEnd) {
			break;
		}
	}
}

Chat.prototype.updateNewestNumber = function ()
{
	ajaxChatLoad("mode=ChatNewestNumber", setNewestNumber);
}

Chat.prototype.getData = function (strQuery)
{
	strQuery = "mode=Chat&number=" + this.iNewestNumber + "&" + strQuery;

	Form.getInputs('chatform').each(function(obj)
	{
		if (obj.type != 'text') {
			obj.disabled = true;
		}
	});

	ajaxChatLoad(strQuery, onPageLoad);
}

Chat.prototype.update = function ()
{
	$('sendtype').innerHTML = typeArray[g_iSendType];

	// カレントの番号が-1なら取得する (起動時)
	if (this.iNewestNumber == -1) {
		this.updateNewestNumber();
	} else {
		this.getData("");
	}
}

Chat.prototype.send = function (str)
{
	$('chatframe').scrollTop = 0;

	if (str == "") {
		updateChat();
		return "";
	}

	// コマンド関連
	if (str.substring(0, 1) == "/" && str.substring(0, 2) != "//") {
		var aCommand = str.substring(1, str.length).split(" ");

		// ショートカット系
		if (aCommand[0] == "h") {
			aCommand[0] = "help";
		}
		if (aCommand[0] == "f") {
			aCommand[0] = "filter";
		}
		if (aCommand[0] == "fn") {
			aCommand[2] = aCommand[1];
			aCommand[0] = "filter";
			aCommand[1] = "on";
		}
		if (aCommand[0] == "ff") {
			aCommand[2] = aCommand[1];
			aCommand[0] = "filter";
			aCommand[1] = "off";
		}
		if (aCommand[0] == "c") {
			aCommand[0] = "clear";
		}
		if (aCommand[0] == "a") {
			aCommand[0] = "all";
		}
		if (aCommand[0] == "all") {
			aCommand[0] = "chat";
			aCommand[1] = "all";
		}
		if (aCommand[0] == "p") {
			aCommand[0] = "party";
		}
		if (aCommand[0] == "party") {
			//this.setFilter(CHAT_FILTER_PARTY | CHAT_FILTER_SYSTEM | CHAT_FILTER_ADMIN);
			aCommand[0] = "chat";
			aCommand[1] = "party";
		}
		if (aCommand[0] == "w") {
			aCommand[0] = "wis";
		}
		if (aCommand[0] == "wis") {
			aCommand[2] = aCommand[1];
			aCommand[0] = "chat";
			aCommand[1] = "wis";
		}
		if (aCommand[0] == "m") {
			aCommand[0] = "mail";
		}

		// ヘルプ
		if (aCommand[0] == "help") {
			this.resv("システム", "[コマンド一覧]<br />" + 
								  "/help : ヘルプの表示<br />" + 
								  "/clear : 表示をクリア<br />" + 
								  "/all : 全体チャット<br />" + 
								  "/wis [name] : 耳打ち<br />" + 
								  "/party : パーティチャット<br />" + 
								  "/mail [name] [subject] : メーラー起動<br />" + 
								  "/filter [on/off/onall/offall] [all/wis/party/system] : 表示するログを変更<br />" +
								  "/konata こなた"
								  , CHAT_TYPE_SYSTEM2);
		} else if (aCommand[0] == "filter") {	// 簡易フィルター
			var iBit = 0;
			var iFlag = this.iFilter;

			if (aCommand[2] == "all") {
				iBit = CHAT_FILTER_ALL;
			} else if (aCommand[2] == "wis") {
				iBit = CHAT_FILTER_WIS;
			} else if (aCommand[2] == "party") {
				iBit = CHAT_FILTER_PARTY;
			} else if (aCommand[2] == "system") {
				iBit = CHAT_FILTER_SYSTEM;
			}

			if (aCommand[1] == "on") {
				iFlag = addFlag(iFlag, iBit);
			} else if (aCommand[1] == "off") {
				iFlag = delFlag(iFlag, iBit);
			} else if (aCommand[1] == "onall") {
				iFlag = CHAT_FILTER_ENABLE_ALL;
			} else if (aCommand[1] == "offall") {
				iFlag = 0;
			}

			this.setFilter(iFlag);
		} else if (aCommand[0] == "clear") {	// 画面のクリア
			this.clear();
			this.render();
		} else if (aCommand[0] == "chat") {	// 発言タイプの変更
			if (aCommand[1] == "all") {
				g_iSendType = CHAT_TYPE_ALL;
				g_iWisName  = "";
			} else if (aCommand[1] == "wis") {
				if (aCommand[2] && aCommand[2] != CHARACTER_NAME) {
					g_iSendType = CHAT_TYPE_WIS;
					g_iWisName = aCommand[2];
					typeArray[CHAT_TYPE_WIS] = '<span class="ft3">Wis to ' + g_iWisName + '</span>';
				}
			} else if (aCommand[1] == "party") {
				g_iSendType = CHAT_TYPE_PARTY;
				g_iWisName  = "";
			} else if (aCommand[1] == "guild") {
				g_iSendType = CHAT_TYPE_GUILD;
				g_iWisName  = "";
			}
		} else if (aCommand[0] == "mail") {	// メール
			changeSubWindow(true);
			pageLoad('MailWrite',	'&to=' + (aCommand[1] ? aCommand[1] : "") +
							 		'&sub=' + (aCommand[2] ? aCommand[2] : ""), 'subwindow');
		} else if (aCommand[0] == "version") {	// バージョン
			this.resv("システム", "Konata☆Chat Copyright &copy; 2007-2008 Akkima.", CHAT_TYPE_SYSTEM2);
		} else if (aCommand[0] == "konata") {	// こなた
			this.resv("システム", '<div style="font-size: 16px; font-family: ＭＳ Ｐゴシック;">' +
								  "　　　　　　　　　　　　　　,,=＝=､､ <br />" +
								  "　　　　　　　　　　　 　 //　　　　ヾ､ <br />" +
								  "　　 　 　 　 　 　 　 　 l:|　　　　　　ヾ. <br />" +
								  "　 　 　 　 　 　 　 ＿＿!__/:ヽ､＿＿_l|_ <br />" +
								  "　　　　　　,. -‐_´:-: : : : : l: : : : : : : : : : :`: .､ <br />" +
								  "　 　 　 ／‐／: :,: : : : : :, :l: : : : : : : : : : : : : : :ヽ <br />" +
								  "　　　 　 ／: : /: : : : : /: /l: : : : ﾊ: l: : : : : : : l: :｀､ <br />" +
								  "　　 　 /: ,／/: :/ : : :_LＬ_l: : : l:l レA､:_: : :､: l : : l <br />" +
								  "　　　/／//: : :l : : : ∧/　l: : : ﾘ　l: |丶:｀: : l: l: : :l <br />" +
								  "　　／　//l: : : l: : : /_V＿ヾ: : |l　_ヾ__ヽ: : : l:ll: : :l <br />" +
								  "　 　 　 /│: : ,､: : :lT亦テl ヾ: l　 T示┬l: : W :､:l <br />" +
								  "　　　　　　l : ハ: : ﾊ｀､'::,┤　ヾ 　 P:,:::ﾉ'lヽ: ﾄ｀,:x <br />" +
								  "　　　　　　 V　 ヽ:l: :l　`''´　 ,　　　`''´'．: ヽl_ノ: N <br />" +
								  "　　 　 　 　 ｀　　N: :ゝ､_, ‐\"｀ ､　　　 ノ: : N : : l <br />" +
								  "　　　　　　　　　│: : :,‐´｀　　 ｀l-イﾆ: /: : :ﾊ: : :l <br />" +
								  "　　 　 　 　 　 　 l : ,亠　　　 ‐､l　 ｀〉/: : : l: l: : :l <br />" +
								  "　　　 　 　 　 　 ﾊキ　 _　　 　 ﾋ､､/ /: : :/彡l､: l <br />" +
								  "　　　　　　　　　l//)､ (:::::｀:::､ ,'､ﾞ､l Y : : /〃彡l l <br />" +
								  "　　　　　　　　 /l´ l　'｀,‐ﾆ┬┤l ｀,.l l　/,´／　 |l" +
								  '</div>'
								  , CHAT_TYPE_SYSTEM2);
		} else {	// リトルカオス
			this.resv("システム", "無効なコマンドです。コマンドの一覧は [/help] で見ることが出来ます。", CHAT_TYPE_SYSTEM);
		}

		$('sendtype').innerHTML = typeArray[g_iSendType];

		return "";
	}

	if (str.substring(0, 2) == "//") {
		str = str.substring(1, str.length);
	}

	// 発言
	var strQuery = "mes=" + encodeURIComponent(str) + "&type=" + g_iSendType + "&wis=" + g_iWisName;

	this.getData(strQuery);
}

// 仮想的にチャットを受信したように見せかける関数 (/helpなどで使用)
Chat.prototype.resv = function (strName, strMessage, iType)
{
	var str = g_objChat.iNewestNumber + "\t0\t" + strName + "\t\t" + strMessage + "\t" + getNowTime() + "\t" + iType;

	this.add(str);
	this.render();
}

var g_objChat = new Chat();

function sendChat()
{
	var str = $("chatform").msg.value;
	$("chatform").msg.value = "";

	g_objChat.send(str);
}

function sendChatString(str)
{
	g_objChat.send(str);
}

function updateChat()
{
	g_objChat.update();
}

function clearChat()
{
	g_objChat.clear();
	g_objChat.render();
}

function checkFilter(obj)
{
	sendChatString("/filter " + (obj.checked ? "on " : "off ") + obj.name);
}

function ajaxChatLoad(strQuery, callBack)
{
	new Ajax.Request('./index.php', {
		method: 'post',
		parameters: 'ajax=true&' + strQuery,
		onSuccess : callBack,
		onFailure : function () {
			setTimeout(function()
			{
				Form.enable('chatform');
			}, 100);
		}
	});
}

function onPageLoad(obj)
{
	var strData = "";
	var dataSplited = obj.responseText.split("\n");

	for (var i = 1; i < dataSplited.length; i++) {
		strData += dataSplited[i] + "\n";
	}

	if (strData == "") return;

	if (dataSplited[0] == '<!-- Success -->') {
		// 更新
		g_objChat.add(strData);
		g_objChat.render();
	} else if (dataSplited[0] == '<!-- Failed -->') {
		g_objChat.resv("システム", dataSplited[1], CHAT_TYPE_SYSTEM);
	}

	setTimeout(function()
	{
		Form.enable('chatform');
	}, 100);
}

function setNewestNumber(obj)
{
	if (obj.responseText) {
		g_objChat.iNewestNumber = obj.responseText;

		if (g_objChat.iNewestNumber < 0) {
			g_objChat.iNewestNumber = 0;
		}

		g_objChat.getData("");
	}
}

function addFlag(iFlag, iBit)
{
	return iFlag | iBit;
}

function delFlag(iFlag, iBit)
{
	return iFlag & ~iBit;
}

// 時間を取得しフォーマットして返す
function getNowTime()
{
	var objDate = new Date();

	var iYear    = objDate.getYear();		// 年
	var iMonth   = objDate.getMonth() + 1;	// 月
	var iDate    = objDate.getDate();		// 日
	var iHours   = objDate.getHours();		// 時
	var iMinutes = objDate.getMinutes();	// 分
	var iSeconds = objDate.getSeconds();	// 秒

	// ブラウザによって実装が異なる
	iYear = (iYear < 2000) ? iYear + 1900 : iYear;

	var strMonth   = "0" + iMonth;
	var strDate	= "0" + iDate;
	var strHours   = "0" + iHours;
	var strMinutes = "0" + iMinutes;
	var strSeconds = "0" + iSeconds;
	strMonth = strMonth.substring(strMonth.length - 2, strMonth.length);
	strDate = strDate.substring(strDate.length - 2, strDate.length);
	strHours = strHours.substring(strHours.length - 2, strHours.length);
	strMinutes = strMinutes.substring(strMinutes.length - 2, strMinutes.length);
	strSeconds = strSeconds.substring(strSeconds.length - 2, strSeconds.length);

	var strTime = iYear + "-" + strMonth + "-" + strDate + " " + strHours + ":" + strMinutes + ":" + strSeconds;

	return strTime;
}