/*
本日もChatPadをご利用頂きありがとうございます！
ソースの確認までして頂き恐縮です！(/ω＼*)
問題がある部分や御意見等ございましたら、ご連絡いただければ幸いです。
連絡先: http://www.monolis.co.jp
*/

var IS_REAL_SERVER = false;
var IS_DEBUG = false;

var CHAT_STATE_INDEX_PAGE = 0;
var CHAT_STATE_WAIT_OTHER = 1;
var CHAT_STATE_CHATING = 2;
var CHAT_STATE_LEAVE_OTHER = 3;
var chatState = CHAT_STATE_INDEX_PAGE;

var ADVS = new Array(
    "<a href='http://d.hatena.ne.jp/villa303/20090715'>ChatPad（チャットパッド）のプレスリリースは開発者ブログでご覧くださ～い！</a>",
    "お友達に「ChatPad」を紹介してくれませんか？",
    "<a href='http://www.monolis.co.jp'>「ChatPad」についての要望があれば聞かせてね！</a>",
    "<a href='http://www.monolis.co.jp'>ChatPadの運営会社モノリスは、Webサービス開発のお仕事を募集中ですよ！</a>",
    "<a href='http://www.monolis.co.jp'>モノリスと一緒に新しいWebサービスを作りませんか？？あなたのアイデアを聞かせてね</a>"
);

var APP_SERVER_BASE;
var WEB_SERVER_BASE;

if (location.href.toLowerCase().indexOf("http://chatpad.jp") == 0) {
    IS_REAL_SERVER = true;
}

if (IS_REAL_SERVER) {
    IS_DEBUG = false;
    APP_SERVER_BASE = "http://chatpad.jp:8080/ChatPad/";
    WEB_SERVER_BASE = "http://chatpad.jp/";
} else {
    APP_SERVER_BASE = "";
    WEB_SERVER_BASE = "";
}

var IMAGE_BASE = WEB_SERVER_BASE + "images/";

function isNeedIframe() {
    if (IS_REAL_SERVER) {
        return location.href.indexOf(":808") == -1;
        //return navigator.userAgent.indexOf("Firefox/3.5") == -1 && location.href.indexOf(":808") == -1;
    } else {
        return false;
    }
}

$(document).ready(function() {
    if (isNeedIframe()) {
        $("#contentsOuter").hide();
        $("#MTPlayer").hide();
        $("body").append("<iframe style='positon:absolute' id='inframe' src='" + APP_SERVER_BASE + "' frameborder='0'></iframe>")
                 .css("overflow", "hidden");
        $("html").css("overflow-y", "hidden");
        $(window).resize(resizeInframe);
        resizeInframe();
    } else {
        chatState = CHAT_STATE_INDEX_PAGE;
        doStatusNum();
        initAdv();
        initTips();
    }
});

function resizeInframe() {
    var wSize = getWindowSize();
    $("#inframe").css("width", wSize.width + "px")
                 .css("height", wSize.height + "px")
                 .css("border", "0px");
}

function getWindowSize() {
    return {
        height: (jQuery.browser.opera ? document.documentElement.clientHeight : $(window).height()),
        width: (jQuery.browser.opera ? document.documentElement.clientWidth : $(window).width())
    }
}

mousedownEventObject = null;
var calledInitChat = false;
function initChat() {
    if (calledInitChat) return;
    calledInitChat = true;
    
    $("#sayButton").click(function() {
        occurSayEvent();
    }).mouseover(function() {
        $(this).attr("src", IMAGE_BASE + "chat_say_button_over.png");
    }).mouseout(function() {
        $(this).attr("src", IMAGE_BASE + "chat_say_button.png");
    }).mousedown(function() {
        $(this).attr("src", IMAGE_BASE + "chat_say_button_down.png");
    }).mouseup(function() {
        $(this).attr("src", IMAGE_BASE + "chat_say_button_over.png");
    });
    $("#sayField").keydown(function(e){
        if (e.keyCode == 13) {
            if (typingTimerId != null) {
                clearTimeout(typingTimerId);
                typingTimerId = null;
                typing = false;
            }
            occurSayEvent();
            return false;
        } else {
            if (typingTimerId != null) {
                clearTimeout(typingTimerId);
            } else {
                doCMD({'cmd':'d'});
            }
            typing = true;
            typingTimerId = setTimeout("typingTimer()", 5000);
        }
    }).blur(function() {
        sayFieldFocus = false;
         $("#sayFieldHolder").css("background-color", "#CCCCCC");
        checkFocus();
        $("#sayFieldCounter").hide();
    }).focus(function() {
        sayFieldFocus = true;
        checkFocus();
        $("#sayFieldCounter").show();
    }).keyup(function() {
        var val = $(this).val();
        var num = sizeOfHankaku(val);
        if (num <= 120) {
            //$("#sayFieldCounter").text("残り" + (120 - num) + "文字");
            $("#sayFieldCounter").text("");
            $(this).css("color", "black");
        } else {
            var counter = 0;
            while (sizeOfHankaku(val) > 120) {
                val = val.substr(0, val.length - 1);
                counter++;
            }
            //$("#sayFieldCounter").text((num - 120) + "文字オーバー");
            $("#sayFieldCounter").text(counter + "文字オーバー");
            $(this).css("color", "red");
        }
    });
    $("#sayFieldHolder").mouseover(function() {
        $(this).css("background-color", "#03A200")
    }).mouseout(function() {
        if (!sayFieldFocus) $(this).css("background-color", "#CCCCCC");
    });
    $("div#chatLog").mousedown(function(e) {
        mousedownEventObject = e;
        //$(this).css("cursor", "url('images/hand_close.gif') 24 24,move");
    }).mousemove(function(e) {
        if (mousedownEventObject != null) {
            var diff = e.pageY - mousedownEventObject.pageY;
            $(this).scrollTop($(this).scrollTop() - diff);
            mousedownEventObject = e;
            //$(this).css("cursor", "url('images/hand_close.gif') 24 24,move");
        } else {
            //$(this).css("cursor", "url('images/hand_open.cur') 24 24,move");
        }
    }).mouseup(function(e) {
        mousedownEventObject = null;
        //$(this).css("cursor", "url('images/hand_open.gif') 24 24,move");
    }).mousewheel(function(event, delta) {
        $(this).scrollTop($(this).scrollTop() - delta * 30);
        return false;
    }).mouseover(function() {
    });
    $(window).unload(function(){
        finalizeChat();
    }).blur(function() {
        windowFocus = false;
        checkFocus();
    }).focus(function() {
        windowFocus = true;
        checkFocus();
    });
    $("#disconnectButton").click(callbackDisconnectButton).mouseover(function() {
        switch (chatState) {
            case CHAT_STATE_INDEX_PAGE: break;
            case CHAT_STATE_WAIT_OTHER:
                $(this).attr("src", IMAGE_BASE + "chat_disconnect_over.png");
                break;
            case CHAT_STATE_CHATING:
                $(this).attr("src", IMAGE_BASE + "chat_disconnect_over.png");
                break;
            case CHAT_STATE_LEAVE_OTHER:
                $(this).attr("src", IMAGE_BASE + "chat_new_over.png");
                break;
        }
    }).mouseout(function() {
        switch (chatState) {
            case CHAT_STATE_INDEX_PAGE: break;
            case CHAT_STATE_WAIT_OTHER:
                $(this).attr("src", IMAGE_BASE + "chat_disconnect.png");
                break;
            case CHAT_STATE_CHATING:
                $(this).attr("src", IMAGE_BASE + "chat_disconnect.png");
                break;
            case CHAT_STATE_LEAVE_OTHER:
                $(this).attr("src", IMAGE_BASE + "chat_new.png");
                break;
        }
    }).mousedown(function() {
        switch (chatState) {
            case CHAT_STATE_INDEX_PAGE: break;
            case CHAT_STATE_WAIT_OTHER:
                $(this).attr("src", IMAGE_BASE + "chat_disconnect_down.png");
                break;
            case CHAT_STATE_CHATING:
                $(this).attr("src", IMAGE_BASE + "chat_disconnect_down.png");
                break;
            case CHAT_STATE_LEAVE_OTHER:
                $(this).attr("src", IMAGE_BASE + "chat_new_down.png");
                break;
        }
    }).mouseup(function() {
        switch (chatState) {
            case CHAT_STATE_INDEX_PAGE: break;
            case CHAT_STATE_WAIT_OTHER: break;
                $(this).attr("src", IMAGE_BASE + "chat_disconnect_over.png");
                break;
            case CHAT_STATE_CHATING:
                $(this).attr("src", IMAGE_BASE + "chat_disconnect_over.png");
                break;
            case CHAT_STATE_LEAVE_OTHER:
                $(this).attr("src", IMAGE_BASE + "chat_new_over.png");
                break;
        }
    });
    $("#iFace").click(function() {
        addChatLog(0, "ChatPadシステムですσ(・Д・)呼んだー？<br>"
                        + "アイコンを変更するなら画像をアップロードしてね<br>"
                        + "<div class='fileUploadFormHolder'>"
                        + "<form class='fileUploadForm' method='POST' enctype='multipart/form-data' action='"+ APP_SERVER_BASE + "face' target='facePostFrame'>"
                        + "<input type='file' name='filefd'/>"
                        + "<input type='submit' value='アップロード'/>"
                        + "</form></div><br>"
                        + "JPEG形式で1MBまでの画像なら使えると思うよー。<br>");
        $(".fileUploadForm").submit(function() {
            setTimeout("callbackSendFaceFile()", 100);
            return true;
        });
    });
    $("#chatLog").mousedown(function() {
       return false;
    }).get(0).onselectstart = function() { return false; };
    $("img#soundButton").click(function() {
       toggleSound();
    }).show();
    $("div#iProfileWindow").mouseover(function() {
        $("div#iProfileFrame").show();
        iProfileFrameFocus = true;
        mediateIProfileURL();
    }).mouseout(function() {
        iProfileFrameFocus = false;
        mediateIProfileURL();
    });
   
    $("#iProfile").blur(function() {
        iProfileFocus = false;
        mediateIProfileURL();
        if ($(this).val() != oldIProfileValue && chatState == CHAT_STATE_CHATING) {
            doCMD({'cmd':'p', 'content':encodeCMDStr($.trim($(this).val()))});
        }
        originalIProfileValue = $(this).val();
        $(this).val(toFixLineSizeStr(originalIProfileValue, 12));
    }).focus(function() {
        $(this).val(originalIProfileValue);
        iProfileFocus = true;
        mediateIProfileURL();
        oldIProfileValue = $(this).val();
        
    }).val("");
    $("#iURL").blur(function() {
        iURLForus = false;
        mediateIProfileURL();
        if ($(this).val() != oldIURLValue && chatState == CHAT_STATE_CHATING) {
            var v = $.trim($(this).val());
            doCMD({'cmd':'q', 'content':encodeCMDStr(v)});
        }
        originalIURLValue = $(this).val();
        $(this).val(toFixLineSizeStr(originalIURLValue, 12));
    }).focus(function() {
        $(this).val(originalIURLValue);
        iURLForus = true;
        mediateIProfileURL();
        oldIURLValue = $(this).val();
        $(this).select();
    }).val("");
    startAdv();
    stopTips();
}


var iProfileFocus = false;
var iURLForus = false;
var iProfileFrameFocus = false;
var oldIProfileValue = null;
var oldIURLValue = null;
var originalIProfileValue = null;
var originalIURLValue = null;
function mediateIProfileURL() {
    if (iProfileFrameFocus || iProfileFocus || iURLForus) {
        $("#iProfileBorder,#iURLBorder").css("background-color", "#CCCCCC");
        $("#iProfile,#iURL").css("background-color", "#F5F5F5").css("color", "#999999");
    } else {
        $("#iProfileBorder,#iURLBorder").css("background-color", "white");
        $("#iProfile,#iURL").css("background-color", "white").css("color", "#666666");
        if ($.trim($("#iProfile").val()).length == 0 && $.trim($("#iURL").val()).length == 0) {
            $("div#iProfileFrame").hide();
        } else {
            var str = $("#iProfile").val();
            while (sizeOfHankaku(str) > 160) str = str.substr(0, str.length - 1);
            $("#iProfile").val(str);
            str = $("#iURL").val();
            if (str.length > 1024) str = str.substr(0, 1024);
            $("#iURL").val(str);
        }
    }
    if (iProfileFrameFocus) {
        $("#iProfile,#iURL").css("overflow-y", "auto");
    } else if (!iProfileFocus && !iURLForus) {
        $("#iProfile,#iURL").css("overflow-y", "hidden");
    }
}

function toFixLineSizeStr(str, maxLineSize) {
    var lineNum = 0;
    var dest = "";
    for (var i = 0; i < str.length; i++) {
        var c = str.charAt(i);
        if (c != '\r' && c != '\n') {
            var sizeOfC = sizeOfHankaku(c);
            if (lineNum + sizeOfC > maxLineSize) {
                dest += "\n";
                lineNum = 0;
            }
            dest += c;
            lineNum += sizeOfC;
        } else {
            if (lineNum != maxLineSize) {
                dest += c;
                lineNum = 0;
            }
        }
    }
    return dest;
}

function callbackSendFaceFile() {
    $(".fileUploadFormHolder input").attr("disabled", "true");
    $(".fileUploadFormHolder:last").after("<span class='fileUploadFormStatus'>ファイル送信中...</span>");
}

var advTimerId = null;
function initAdv() {
    advPointer = 0;
    callbackAdv();
}

function startAdv() {
    if (advTimerId == null) advTimerId = setInterval("callbackAdv()", 15000);
}

function stopAdv() {
    if (advTimerId != null) clearInterval(advTimerId);
    advPointer = 0;
    callbackAdv();
}

function pauseAdv() {
    if (advTimerId != null) clearInterval(advTimerId);
}

var advPointer = 0;
function callbackAdv() {
    if (advPointer >= ADVS.length) advPointer = 0;
    $("div#footerAdv").html(ADVS[advPointer]);
    $("div#footerAdv a").attr("target", "_blank").mouseover(function() {
        $(this).css("text-decoration", "underline");
    }).mouseout(function() {
        $(this).css("text-decoration", "none");
    });
    advPointer++;
}

function callbackDisconnectButton() {
    if (chatState == CHAT_STATE_CHATING) {
        if (confirm("チャット中です。\nチャットを終了してもよろしいですか？")) {
            addChatLog(0, "お疲れ～っす。ChatPadシステムです (・Д・)&gt;<br>"
                            + "チャットを終了したよ！<br>"
                            + "もしチャットした相手が不快な人だったら[<span class='evalButton'>ここ</span>]を押して教えてね。<br>"
                            + "新しい相手とチャットするには<br>"
                            + "新規チャットボタンをポチッとな～♪　 (・Д・)b");
            fookEval();
        } else {
            return;
        }
    } else if (chatState == CHAT_STATE_WAIT_OTHER) {
        addChatLog(0, "お疲れ～っす。ChatPadシステムです (・Д・)&gt;<br>"
                        + "チャット相手を見つけるのをやめたよ！<br>"
                        + "チャットするには<br>"
                        + "新規チャットボタンをポチッとな～♪　 (・Д・)b");
    }
    callbackDisconnectCommon();
}

var firstCopy = true;
function callbackCopy() {
    if (sayFieldFocus) {
        return true;
    } else if (chatState == CHAT_STATE_INDEX_PAGE || chatState == CHAT_STATE_WAIT_OTHER) {
        return true;
    } else {
        if (firstCopy) {
            alert("チャット本文の無断転載は原則禁止です。\nどうしても転載したい場合は、チャット相手の承諾を得てください。");
            firstCopy = false;
        }
        return true;
    }
}

function callbackDisconnectCommon() {
    var button = $("#disconnectButton");
    if (chatState == CHAT_STATE_CHATING || chatState == CHAT_STATE_WAIT_OTHER) {
        stopChat();
        button.attr("src", IMAGE_BASE + "chat_new.png");
    } else if (chatState == CHAT_STATE_LEAVE_OTHER) {
        startChat();
        button.attr("src", IMAGE_BASE + "chat_disconnect.png");
    }
}

function fookEval() {
    $(".evalButton").click(function() {
        doCMD({'cmd':'v', 'content':'l'});
        addChatLog(0, "教えてくれてありがとう♪<br>参考にするよー (・Д・)b");
        $(this).unbind('click');
    });
}

var windowFocus = false;
var sayFieldFocus = false;
function checkFocus() {
    if ((chatState == CHAT_STATE_CHATING) && (sayFieldFocus || windowFocus)) stopTitleBarNotify();
}

var typing = false;
var typingTimerId = null;
function typingTimer() {
    typingTimerId = null;
    typing = false;
    doCMD({'cmd':'u'});
}


var startChatTimerId = null;
var chatHistory = new Array();
function callbackStartChatTimer() {
    doCMD({'cmd':'chat.start'});
}

function startStartChatSignal() {
    stopStartChatSignal();
    var shortCnt = 0;
    if (chatHistory.length >= 3) {
        for (var i = chatHistory.length - 1; i >= 0; i--) {
            if (chatHistory[i] <= 5) shortCnt++;
            else shortCnt--;
        }
    }
    if (shortCnt <= 0) callbackStartChatTimer();
    else startChatTimerId = setTimeout("callbackStartChatTimer()", shortCnt * 1000 * 15);
}

function stopStartChatSignal() {
    if (startChatTimerId != null) clearTimeout(startChatTimerId);
}

function startChat() {
    if (chatState == CHAT_STATE_INDEX_PAGE || chatState == CHAT_STATE_LEAVE_OTHER) {
        startCMDSender();
        $(".message").remove();
        $("#sayField").val("");
        $(".eval").removeClass("evalSelect");
        $(".eval:first").addClass("evalSelect");
        chatState = CHAT_STATE_WAIT_OTHER;
        $("#reFace").attr("src", IMAGE_BASE + "redummy.png");
        $("#disconnectButton ").attr("src", IMAGE_BASE + "chat_disconnect.png");
        //doCMD({'cmd':'chat.start'});
        startStartChatSignal();

        var s = "どもー。ChatPadシステムです (・Д・)ノ<br>"
              + "チャットが始まる前に少しだけ利用規約のお話をさせてね！<br>"
              + "・楽しいチャットにするために相手を不快にする発言はしないでね<br>"
              + "・恋人探しや、会うことだけを目的にした利用はしないようにね<br>"
              + "・個人情報は自分で守ってね<br>"
              + "・チャット本文やスクリーンショットを第三者に公開しないでね<br>"
              + "・違法行為や犯罪行為、営利行為につながる発言は禁止だよ<br>"
              + "<br>"
              + "みんなが楽しく使えるチャットサービスにするために<br>"
              + "ChatPadとの約束だよ！　(・Д・)b";
        addChatLog(0, s);
        addChatLog(0, "ChatPadシステムです (・Д・)&gt;<br>チャット相手を探してるのでしばらく待ってね！");
        $("#soundButton").show();
    }
    startAdv();
}

function stopChat() {
    if (chatState == CHAT_STATE_CHATING || chatState == CHAT_STATE_WAIT_OTHER) {
        chatState = CHAT_STATE_LEAVE_OTHER;
        stopStartChatSignal();
        stopTitleBarNotify();
        $("#reFace").attr("src", IMAGE_BASE + "redummy.png");
        doCMD({'cmd':'x'});
        initReProfile();
        playSound(SOUND_CHAT_END);
    }
}

function finalizeChat() {
    stopCMDSender();
    doAsyncCMD({'cmd':'o'});
    stopPooling();
    chatState = CHAT_STATE_INDEX_PAGE;
    stopTitleBarNotify();
    $("#reFace").attr("src", IMAGE_BASE + "redummy.png");
    $("#iFace").attr("src", IMAGE_BASE + "idummy.png");
    $("div#indexContents").css("display", "block");
    $("div#chatContents").css("display", "none");
    $("#headLogo").css("cursor", "auto").unbind().removeAttr("title");
    $("#soundButton").hide();
    $("#iProfile").val("");
    $("#iURL").val("");
    stopAdv();
    startTips();
}

function toCommaString(strOrInt) {
    var num = new String(strOrInt).replace(/,/g, "");
    while(num != (num = num.replace(/^(-?\d+)(\d{3})/, "$1,$2")));
    return num;
}

function doStatusNum() {
    if (chatState == CHAT_STATE_INDEX_PAGE) {
        $.ajax({
            url: APP_SERVER_BASE + 'status',
            cache: false,
            type: "POST",
            data: {'cmd':'n'},
            dataType: "text",
            /*timeout: 5000,*/
            success: function(text) {
                var userSize = parseInt(text.split('\t')[0]);
                var msgSize  = parseInt(text.split('\t')[1]);
                if (chatState == CHAT_STATE_INDEX_PAGE) {
                    if (userSize  < 1800) {
                        $("#startChatButton").unbind().click(function() {
                            $("div#indexContents").css("display", "none");
                            $("div#chatContents").css("display", "block");
                            initChat();
                            $("#headLogo").click(function() {
                                if (chatState == CHAT_STATE_CHATING) {
                                    if(confirm('チャットを終了してトップページ戻りますか？')) {
                                        stopChat();
                                    } else {
                                        return;
                                    }
                                } else if (chatState == CHAT_STATE_WAIT_OTHER) {
                                    stopChat();
                                }
                                finalizeChat();
                            }).css("cursor", "pointer").attr("title", "トップページ戻る");
                            startChat();
                        }).mouseover(function() {
                            this.src = IMAGE_BASE + "startbutton_over.png";
                        }).mouseout(function() {
                            this.src = IMAGE_BASE + "startbutton.png";
                        }).mousedown(function() {
                            this.src = IMAGE_BASE + "startbutton_click.png";
                        });
                        $("#indexMainButtonNote").text("");
                    } else {
                        $("#startChatButton").unbind();
                        $("#indexMainButtonNote").text("サーバーが混み合っています。そのまま、しばらくお待ち下さい。");
                    }
                }
                $("#msgSize").text(toCommaString(msgSize) + "件");
                $("#userSize").text(toCommaString(userSize) + "人");
            },
            error : function(XMLHttpRequest, textStatus, errorThrown) {
                $("#indexMainButtonNote").text("サーバーが混み合っているか、ご利用のインターネット環境からはご利用できない可能性があります。");
            },
            beforeSend : function(XMLHttpRequest) {
                //XMLHttpRequest.setRequestHeader("X-PINGARUNER", "pingpong");
            },
            complete : function(XMLHttpRequest, textStatus){
                setTimeout("doStatusNum()", 60000);
            }
        });
    } else {
        doCMD({'cmd':'a'});
        setTimeout("doStatusNum()", 120000);
    }
}

var cmdTimerId = null;
var runningCMDSender = false;
function startCMDSender() {
    cmdTimerId = null;
    runningCMDSender = true;
    cmdQue = new Array();
    sendingCMDQue = new Array();
    cmdSenderXHR = null;
}

function stopCMDSender() {
    runningCMDSender = false;
    if (cmdTimerId != null) {
        clearTimeout(cmdTimerId);
        cmdTimerId = null;
    }
    if (cmdSenderXHR != null) {
        cmdSenderXHR.abort();
        cmdSenderXHR = null;
    }
}

var sendingCMDQue = new Array();
var cmdSenderXHR = null;
function callbackCMDTimer() {
    if (runningCMDSender && cmdQue.length > 0) {
        while (sendingCMDQue.length > 0) sendingCMDQue.shift();
        var content = "";
        var cmd;
        while (cmdQue.length > 0) {
            cmd = cmdQue.shift();
            sendingCMDQue.push(cmd);
            content += cmd["cmd"] + "\t" + cmd["content"] + "\n";
        }
        if (sendingCMDQue.length != 1) {
            cmd = {'cmd':'pkg','content': content};
        }
        cmdSenderXHR = $.ajax({
            url: APP_SERVER_BASE + 'cmd',
            cache: false,
            type: "POST",
            data: cmd,
            timeout: 5000,
            dataType: "text",
            success: function(text) {
                if (text == "chat.start" /* || text == "REQ.REQ" */ ) {
                    if (haltPooling) {
                        haltPooling = false;
                        pooling();
                    }
                }
                if (runningCMDSender) {
                    if (cmdQue.length > 0) {
                        cmdTimerId = setTimeout("callbackCMDTimer()", 1000);
                    } else {
                        cmdTimerId = null;
                    }
                } else {
                    cmdTimerId = null;
                }
            },
            error : function(XMLHttpRequest, textStatus, errorThrown) {
                while (sendingCMDQue.length > 0) cmdQue.unshift(sendingCMDQue.pop());
                if (runningCMDSender) {
                    cmdTimerId = setTimeout("callbackCMDTimer()", 3000);
                } else {
                    cmdTimerId = null;
                }
            },
            beforeSend : function(XMLHttpRequest) {
                // XMLHttpRequest.setRequestHeader("X-PINGARUNER", "pingpong"); //use cross-site
            },
            complete : function(XMLHttpRequest, textStatus){
                cmdSenderXHR = null;
            }
         });
    } else {
        cmdTimerId = null;
    }
}

var cmdQue = new Array();
function doCMD(cmd) {
    if (cmd == null || !runningCMDSender) return;
    cmdQue.push(cmd);
    if (cmdTimerId == null) {
        cmdTimerId = setTimeout("callbackCMDTimer()", 1000);
    }


}

function doAsyncCMD(cmd) {
    $.ajax({
        url: APP_SERVER_BASE + 'cmd',
        cache: false,
        type: "POST",
        data: cmd,
        dataType: "text"
    });
}

var haltPooling = true;
var poolingXHR = null;
var poolingErrorTimerId = null;
function pooling() {
    poolingErrorTimerId = null;
    if (haltPooling) return;

    poolingXHR = $.ajax({
      url: APP_SERVER_BASE + 'notify',
      cache: false,
      dataType: "text",
      timeout: 4.5 * 60 * 1000,
      success: function(text) {
          if (text != null) {
              if (text == "[wait]") {
                  finalizeChat();
              } else {
                  var lines = text.split("\n");
                  for (var i = 0; i < lines.length; i++) {
                      var line = lines[i];
                      if (line.length != 0 && line != "[wait]") {
                          var cmd = line.charAt(0);
                          var content = (line.length > 1) ? line.substring(1) : "";
                          if (!executer(cmd, content)) {
                              haltPooling = true;
                              break;
                          }
                      }
                  }
              }
          }
          if (!haltPooling) pooling();
      },
      error : function(XMLHttpRequest, textStatus, errorThrown) {
          if (!haltPooling) {
              poolingXHR = null;
              poolingErrorTimerId = setTimeout("pooling()", 3000);
          } else {
              poolingErrorTimerId = null;
          }
      },
      beforeSend : function(XMLHttpRequest) {
          XMLHttpRequest.setRequestHeader("X-PINGARUNER", "pingpong");
      }
    });

}

function stopPooling() {
    haltPooling = true;
    if (poolingErrorTimerId != null) {
        clearTimeout(poolingErrorTimerId);
        poolingErrorTimerId = null;
    }
    if (poolingXHR != null) {
        poolingXHR.abort();
        poolingXHR = null;
    }
}

function executer(cmd, content) {
    switch (cmd) {
        case "s" :
            executerSystem(content);
            break;
        case "S" :
            addChatLog(0, content);
            break;
        case "O":
            addChatLog(2, content);
            if (!(sayFieldFocus || windowFocus)) startTitleBarNotify();
            break;
        case "o":
            setOtherTyping(content == "d");
            break;
        case "n":
            pushUploadFaceFile(0, content);
            break;
        case "p":
            pushUploadFaceFile(1, content);
            break;
        case "a":
            $("#userSize").text(toCommaString(content) + "人");
            break;
        case "b":
            $("#msgSize").text(toCommaString(content) + "件");
            break;
        case "q":
            if (chatState == CHAT_STATE_CHATING) {
                $("#reProfile").html(decodeCMDStr(escapeHtml(toFixLineSizeStr(content, 12))));
                reProfileChanged();
            }
            break;
        case "r":
            if (chatState == CHAT_STATE_CHATING) {
                $("#reURL").html(escapeHtml(toFixLineSizeStr(content, 12)));
                reProfileChanged();
            }
            break;
    }

    return true;
}

function executerSystem(content) {
    switch (content) {
        // チャット相手を待ち中
        case "w":
            //addChatLog(0, "ChatPadシステムです (・Д・)&gt;<br>チャット相手を探してるのでしばらく待ってね！");
            break;
        // チャット相手が見つかったためチャット開始
        case "s":
            addChatLog(0, "ChatPadシステムです (・Д・)&gt;<br>チャット相手が見つかったので<br>チャットを始めるよー！");
            chatState = CHAT_STATE_CHATING;
            chatHistory.push(0);
            playSound(SOUND_CHAT_START);
            if ($.trim($("#iProfile").val()).length > 0) {
                doCMD({'cmd':'p', 'content':encodeCMDStr($.trim(originalIProfileValue))});
            }
            if ($.trim($("#iURL").val()).indexOf("http") == 0) {
                doCMD({'cmd':'q', 'content':encodeCMDStr($.trim(originalIURLValue))});
            }
            break;
        // チャット相手が退出
        case "e":
            addChatLog(0, "どもー。ChatPadシステムです (・Д・;)&gt;<br>"
                            + "チャット相手がチャットを終了したよ！<br>"
                            + "もしチャットした相手が不快な人だったら[<span class='evalButton'>ここ</span>]を押して教えてね。<br>"
                            + "新しい相手とチャットするには<br>"
                            + "新規チャットボタンをクリック、クリック～♪　 (・Д・)b");
            fookEval();
            chatHistory[chatHistory.length - 1] = 100;
            callbackDisconnectCommon();
            break;
        case "m":
            addChatLog(0, "相手とChatPadシステムとの通信が途絶えています。<br>"
                            + "しばらく待ったら回復するかも。");
            break;
    }
}

function initReProfile() {
    $("#reProfile").text("");
    $("#reURL").text("");
    reProfileChanged();
}

function reProfileChanged() {
    if ($("#reProfile").text().length > 0 || $("#reURL").text().length > 0) {
        $("#reProfileWindow").show();
    } else {
        $("#reProfileWindow").hide();
    }
}

function pushUploadFaceFile(meOther, content) {
    var url;
    if (meOther == 0) {
        url = WEB_SERVER_BASE + ((content == "") ? "images/idummy.png" : "face/" + content);
        $("img#iFace").attr("src", url);
        if (content == "") {
            $(".fileUploadFormStatus:last").text("ファイル送信失敗");
            addChatLog(0, "ChatPadシステムです (・Д・)&gt;<br>アイコンの更新に失敗しました。");
        } else {
            $(".fileUploadFormStatus:last").text("ファイル送信完了");
        }
    } else {
        url = WEB_SERVER_BASE + ((content == "") ? "images/redummy.png" : "face/" + content);
        $("img#reFace").attr("src", url);
    }
}

function occurSayEvent() {
    var v = $.trim($("#sayField").val());
    if (v != "") {
        while (sizeOfHankaku(v) > 120) {
            v = v.substr(0, v.length - 1);
        }
        doCMD({'cmd':'M','content': v});
        addChatLog(1, v);
        chatHistory[chatHistory.length - 1]++;
    }
    $("#sayField").val("").focus();
}

/** チャットログに発言を追加
 * @param systemMeOther int 0:システム 1:自分 2:相手 3:相手タイピング
 * @param msg string 発言内容
 * @return void
 */
function addChatLog(systemMeOther, msg) {
    var IMG_TOP_HEIGHT = 16;
    var IMG_BOTTOM_HEIGHT = 27;
    var imgWidth;
    var lineSize;
    var imgPreFix = IMAGE_BASE;

    switch (systemMeOther) {
        case 1:
            imgWidth = 227;
            lineSize = 24;
            imgPreFix += "i_";
            break;
        case 2:
            imgWidth = 227;
            lineSize = 24;
            imgPreFix += "re_";
            setOtherTyping(false);
            break;
        case 3:
            imgWidth = 227;
            lineSize = 24;
            imgPreFix += "re_";
            setOtherTyping(false);
            break;
        default:
            imgWidth = 404;
            lineSize = 64;
            imgPreFix += "system_";
    }

    var lineNum = Math.floor(((sizeOfHankaku(msg) - 1) / lineSize)) + 1;
    if (systemMeOther == 0) {
        lineNum = msg.split("<br>").length;
    }
    var imgMiddleHeight = (lineNum - 1) * 20;

    var balloon = $(document.createElement("div"))
                    .addClass("message")
                    .css("height", IMG_TOP_HEIGHT + imgMiddleHeight + IMG_BOTTOM_HEIGHT + "px");
    var imgTop = $(document.createElement("img"))
                    .attr("src", imgPreFix + "top.gif")
                    .css("position", "absolute")
                    .css("left", "0px")
                    .css("top", "0px");
    var imgMiddle = $(document.createElement("div"))
                    .css("background-image", "url('" + imgPreFix + "middle.gif')")
                    .css("position", "absolute")
                    .css("left", "0px")
                    .css("width", imgWidth + "px")
                    .css("top", IMG_TOP_HEIGHT + "px")
                    .css("height", imgMiddleHeight + "px");
    var imgBottom = $(document.createElement("img"))
                    .attr("src", imgPreFix + "bottom.gif")
                    .css("position", "absolute")
                    .css("left", "0px")
                    .css("top", IMG_TOP_HEIGHT + imgMiddleHeight + "px");
    var text = $(document.createElement("div"));

    var lastMsg = $(".message:last");
    var top = 0;
    if (lastMsg.size() != 0) top = trimPxToInt(lastMsg.css("top")) + lastMsg.height() + 10;
    balloon.css("top", top + "px").css("display", "none");

    switch (systemMeOther) {
        case 1:
            balloon.addClass("myMessage");
            balloon.append(imgTop).append(imgMiddle).append(imgBottom).append(text.html(escapeHtml(toFixLineSizeStr(msg,24))).addClass("textInI"));
            //playSound(SOUND_MESSAGE_SEND);
            break;
        case 2:
            balloon.append(imgTop).append(imgMiddle).append(imgBottom).append(text.html(escapeHtml(toFixLineSizeStr(msg,24))).addClass("textInRe"));
            playSound(SOUND_MESSAGE_RECEIVE);
            break;
        case 3:
            balloon.addClass("otherMessage");
            balloon.append(imgTop).append(imgMiddle).append(imgBottom).append(text.html(escapeHtml(msg)).addClass("textInRe")).addClass("typing");
            break;
        default:
            balloon.addClass("systemMessage");
            balloon.append(imgTop).append(imgMiddle).append(imgBottom).append(text.html(msg).addClass("textInSystem"));
            //playSound(SOUND_SYSTEM_RECEIVE);
    }

    $("#chatLog").append(balloon);

    balloon.fadeIn();
    $("#chatLog").scrollTop(top);
}

function trimPxToInt(XXpxStr) {
    return parseInt(XXpxStr.substr(0, XXpxStr.length - 2));
}

function escapeHtml(str) {
    str = escapeTag(str);
    if (str.indexOf("http://") == 0 && str.indexOf("///") == -1) {
        str = "<a href='" + str + "' target='_blank' title='新しいウィンドウで外部サイトを開きます。'>" + str + "</a>";
    }
    return str;
}

function escapeTag(str) {
    str = str.replace(/</g, "&lt;");
    str = str.replace(/>/g, "&gt;");
    str = str.replace(/"/g, "&quot;");
    str = str.replace(/ /g, "&nbsp;");
    return str;
}

function setOtherTyping(typingOrStop) {
    var typing = $("div.typing");
    if (typing.size() == 0) {
        if (typingOrStop) {
            addChatLog(3, "(入力中...)");
        }
    } else {
        if (!typingOrStop) {
            if ($(".message:last").get(0) != typing.get(0)) {
                var top = trimPxToInt(typing.css("top"));
                typing.nextAll("div.message").each(function() {
                    $(this).css("top", top + "px");
                    top += $(this).height() + 10;
                });
                $("#chatLog").scrollTop(top);
            }
            typing.remove();
        }
    }

}

function sizeOfHankaku(str) {
    if (str == null) return 0;
    var counter = 0;
    for (var i = 0; i < str.length; i++) {
        var c = str.charCodeAt(i);
        if ( (c >= 0x0 && c < 0x81) || (c == 0xf8f0) || (c >= 0xff61 && c < 0xffa0) || (c >= 0xf8f1 && c < 0xf8f4)) {
            counter++;
        } else {
            counter += 2;
        }
    }
    return counter;
}

function setFavicon(toggleActiveGray) {
    var next;
    switch (toggleActiveGray) {
        case 0:
            next = ($("#favicon").attr("href") == "favicon.ico") ? "favicon_gray.ico" : "favicon.ico";
            break;
        case 1:
            next = "favicon.ico";
            break;
        case 2:
            next = "favicon_gray.ico";
            break;
    }
    $('#favicon').remove();
    $('meta:last').after($(document.createElement('link'))
                  .attr('id', 'favicon').attr('rel', 'shortcut icon').attr('href', next));
    return (next == "favicon.ico") ? 1 : 2;
}

var titleBarNotifiy = false;
var titleBarNotifiyTimer = null;
function startTitleBarNotify() {
    if (!titleBarNotifiy) {
        titleBarNotifiy = true;
        titleBarNotifiyTimer = setInterval("setFavicon(0)", 1000);
    }
}

function stopTitleBarNotify() {
    titleBarNotifiy = false;
    clearInterval(titleBarNotifiyTimer);
    setFavicon(1);
}

function callbackTitleBarNotify() {
    setFavicon(0);
}

function player() {
    return document.all ? window["MTPlayer"] : document["MTPlayer"];
}

var isInitializedMTP = false;
function initializedMonolisTinyPlayer() {
    isInitializedMTP = true;
}

var SOUND_CHAT_END = "chat_end.mp3";
var SOUND_CHAT_START = "chat_start.mp3";
var SOUND_MESSAGE_RECEIVE = "message_receive.mp3";
var SOUND_MESSAGE_SEND = "message_send.mp3";
var SOUND_SYSTEM_RECEIVE = "system_receive.mp3";
var SOUND_TYPING = "typing.mp3";
function playSound(soundType) {
    if (!isInitializedMTP || !soundOnOff) return;
    player().doPlayFile(WEB_SERVER_BASE + "sound/" + soundType);
}

var soundOnOff = true;
function toggleSound() {
    soundOnOff = !soundOnOff;
    $("img#soundButton").attr("src", IMAGE_BASE + (soundOnOff ? "sound_on.png" : "sound_off.png"));
}

var tips = null;
var tipsTimerId = null;
function initTips() {
    $.ajax({
        url: APP_SERVER_BASE + 'tips.txt',
        cache: false,
        type: "GET",
        dataType: "text",
        success: function(text) {
            tips = trim(text).split("\n").reverse();
            startTips();
            callbackTipsTimer();
        }
    });
}

function startTips() {
//    stopTips();
//    if (tips != null) {
//        tipsTimerId = setInterval("callbackTipsTimer()", 7000);
//        $(".tip").unbind().mouseover(stopTips).mouseout(startTips);
//    }
}

function stopTips() {
//    if (tipsTimerId != null) {
//        clearInterval(tipsTimerId);
//        tipsTimerId = null;
//    }
}

function callbackTipsTimer() {
//    for (var i = 0; i < 6; i++) {
//        var tip = tips[i].split(",");
//        $("#tip" + i + " a").attr("href", tip[0]);
//        $("#tip" + i + " img").attr("src", tip[1]);
//    }
//    tips.push(tips.shift());
//    tips.push(tips.shift());
//    tips.push(tips.shift());

    for (var i = 0; i < 6; i++) {
        var tip = tips[i].split(",");
        $("#tip" + i + " a").attr("href", tip[0]);
        $("#tip" + i + " img").attr("src", tip[1]);
    }
}

function trim(str) {
    return (str == null) ? str : str.replace(/^\s+|\s+$/g, "");
}

function encodeCMDStr(str) {
    return (str == null) ? str : str.replace(/(\r\n|\n)/g,'\r');
}

function decodeCMDStr(str) {
    if (str == null)  {
        return str;
    } else {
        str = escapeTag(str);
        return str.replace(/\r/g,"<br>");
    }
}