/*
本日も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 CHAT_STATE_STANDALONE = 4;
var chatState = CHAT_STATE_INDEX_PAGE;

var ADVS = new Array(
    " <a href='http://blog.monolis.co.jp/category/service/chatpad/'>新着お知らせ</a> ｜ <a href='http://blog.monolis.co.jp/2009/07/15/chatpad%EF%BD%9C%E3%83%97%E3%83%AC%E3%82%B9%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9/'>ChatPadについて</a> ｜ <a href='http://blog.monolis.co.jp/2009/08/20/chatpad%EF%BD%9C%E3%83%98%E3%83%AB%E3%83%97/'>ヘルプ</a> ｜ <a href='http://blog.monolis.co.jp/2009/08/20/chatpad%EF%BD%9C%E3%81%94%E6%84%8F%E8%A6%8B%E3%83%BB%E3%81%94%E8%A6%81%E6%9C%9B/'>ご意見・ご要望</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;
var FACE_BASE;

if (location.href.toLowerCase().indexOf("http://chatpad.jp") == 0) {
    IS_REAL_SERVER = true;
}

if (IS_REAL_SERVER) {
    IS_DEBUG = false;
    APP_SERVER_BASE = isMixi() ? "http://chatpad.jp:8080/mixi/" : "http://chatpad.jp:8080/ChatPad/";
    WEB_SERVER_BASE = "http://chatpad.jp/";
    FACE_BASE = WEB_SERVER_BASE + (isMixi() ? "mixiface/" : "face/");
} else {
    APP_SERVER_BASE = "";
    WEB_SERVER_BASE = "";
    FACE_BASE = WEB_SERVER_BASE + "face/";
}

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;
        //if (!isMixi()) $("#adBannerFrame").show().attr("src", "http://ad.chatpad.jp/get.php");
        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;
var mscroll = null;
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;
            if (mscroll != null) mscroll.repaint();
            //$(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);
        if (mscroll != null) mscroll.repaint();
        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:
            case CHAT_STATE_CHATING:
            case CHAT_STATE_LEAVE_OTHER:
                $(this).attr("src", IMAGE_BASE + "chat_disconnect_over.png"); break;
            case CHAT_STATE_STANDALONE:
                $(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:
            case CHAT_STATE_CHATING:
            case CHAT_STATE_LEAVE_OTHER:
                $(this).attr("src", IMAGE_BASE + "chat_disconnect.png"); break;
            case CHAT_STATE_STANDALONE:
                $(this).attr("src", IMAGE_BASE + "chat_new.png"); break;
        }
    }).mousedown(function() {
        switch (chatState) {
            case CHAT_STATE_INDEX_PAGE: break;
            case CHAT_STATE_WAIT_OTHER:
            case CHAT_STATE_CHATING:
            case CHAT_STATE_LEAVE_OTHER:
                $(this).attr("src", IMAGE_BASE + "chat_disconnect_down.png"); break;
            case CHAT_STATE_STANDALONE:
                $(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:
            case CHAT_STATE_CHATING:
            case CHAT_STATE_LEAVE_OTHER:
                $(this).attr("src", IMAGE_BASE + "chat_disconnect_over.png"); break;
            case CHAT_STATE_STANDALONE:
                $(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(iURLBlur).focus(iURLFocus).val("");
    startAdv();
    stopTips();
    mscroll = new MScroll();
    if (isMixi()) {
        $("#iMixiId").attr("checked", false);
        $("#iMixiId").click(function() {
            var mid = parseMixiId(location.href);
            if (mid != "") {
                iURLFocus();
                if ($(this).attr("checked")) {
                    $("#iURL").val("http://mixi.jp/show_profile.pl?id=" + mid);
                } else {
                    $("#iURL").val("");
                }
                iURLBlur();
            }
        });
    }
}

function parseMixiId(url) {
    var pos = url.indexOf("id=");
    if (pos != -1) {
        var mid = url.substring(pos + 3);
        if (mid.indexOf("&") == -1)
            return mid;
    }
    return "";
}

function iURLBlur() {
    iURLForus = false;
    mediateIProfileURL();
    if ($("#iURL").val() != oldIURLValue && chatState == CHAT_STATE_CHATING) {
        var v = $.trim($("#iURL").val());
        doCMD({'cmd':'q', 'content':encodeCMDStr(v)});
    }
    originalIURLValue = $("#iURL").val();
    $(this).val(toFixLineSizeStr(originalIURLValue, 12));
}

function iURLFocus() {
    $("#iURL").val(originalIURLValue);
    iURLForus = true;
    mediateIProfileURL();
    oldIURLValue = $("#iURL").val();
    $("#iURL").select();
}

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");
        $("#iProfile").css("color", "#666666");
        $("#iURL").css("color", "#F8A02E");
        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;
var advMiddleTimerId = null;
function initAdv() {
    advPointer = 0;
    callbackAdv();
    advTimerId = setInterval("callbackAdvMiddle()", 60000);
}

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 callbackAdvMiddle() {
    var adv = $("#middleAdv iframe");
    if (adv.size() != 0)
        adv.attr("src", adv.attr("src"));
}

function callbackDisconnectButton() {
    if (chatState == CHAT_STATE_CHATING) {
        if (confirm("チャット中です。\nチャットを終了してもよろしいですか？") && chatState == CHAT_STATE_CHATING) {
            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 || chatState == CHAT_STATE_LEAVE_OTHER) {
        stopChat();
        button.attr("src", IMAGE_BASE + "chat_new.png");
    } else if (chatState == CHAT_STATE_STANDALONE) {
        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_STANDALONE) {
        startCMDSender();
        $(".message").remove();
        $("#sayField").val("");
        $(".eval").removeClass("evalSelect");
        $(".eval:first").addClass("evalSelect");
        chatState = CHAT_STATE_WAIT_OTHER;
        $("#reFace").attr("src", IMAGE_BASE + "redummy.png");
        $("#reFaceLink").unbind().click(function() {return false;}).attr("href", "#");
        $("#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) {
        chatState = CHAT_STATE_STANDALONE;
        stopStartChatSignal();
        stopTitleBarNotify();
        $("#reFace").attr("src", IMAGE_BASE + "redummy.png");
        doCMD({'cmd':'x'});
        initReProfile();
        playSound(SOUND_CHAT_END);
        $("#reFaceLink").unbind().click(function() {return false;}).attr("href", "#");
    }
}

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 isMixi() {
    return location.href.indexOf("mixi") != -1;
}

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["content"] == undefined) ? (cmd["cmd"] + "\n") : (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") {
                    if (haltPooling) {
                        haltPooling = false;
                        pooling();
                    }
                } else if (text == "REQ.REQ") {
                    stopPooling();
                    startPooling();
                }
                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 startPooling() {
    stopPooling();
    haltPooling = false;
    pooling();
}

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) {
                if (isMixi()) {
                    if (content == "")
                        $("#reURL").html("");
                    else {
                        var mid = parseMixiId(content);
                        $("#reURL").html("<a href='http://mixi.jp/show_profile.pl?id=" + escapeTag(mid) + "' target='_blank'>" + mid + "</a>");
                    }
                } else {
                    $("#reURL").html(escapeHtml(toFixLineSizeStr(content, 12)));
                }
                
                reProfileChanged();
            }
            break;
    }

    return true;
}

function executerSystem(content) {
    switch (content) {
        // チャット相手を待ち中
        case "w": 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":
            chatState = CHAT_STATE_LEAVE_OTHER;
            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) {
        if (content == "") {
            url = WEB_SERVER_BASE + "images/idummy.png";
        } else {
            url = FACE_BASE + content;
        }
        $("img#iFace").attr("src", url);
        if (content == "") {
            $(".fileUploadFormStatus:last").text("ファイル送信失敗");
            addChatLog(0, "ChatPadシステムです (・Д・)&gt;<br>アイコンの更新に失敗しました。");
        } else {
            $(".fileUploadFormStatus:last").text("ファイル送信完了");
        }
    } else {
        if (content == "") {
            url = WEB_SERVER_BASE + "images/idummy.png";
        } else {
            url = FACE_BASE + content;
        }
        $("img#reFace").attr("src", url);
        if (content == "") {
            $("#reFaceLink").unbind().click(function() {return false;}).attr("href", "#");
        } else {
            $("#reFaceLink").unbind().click(function() {return true;}).attr("href", "face");
        }
    }
}

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);

    if (mscroll != null) mscroll.repaint();
}

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;");
    str = str.replace(/'/g, "&#39;");
    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>");
    }
}

function MScroll() {
    var jTarget = $("#chatLog");
    var jmScroll = $(".mScroll");
    var jmButton = $(".mScrollButton");
    var jmButtonTop = $(".mScrollButtonTop");
    var jmButtonMiddle = $(".mScrollButtonMiddle");
    var jmButtonBottom = $(".mScrollButtonBottom");
    var jmUpArea = $(".mScrollUpArea");
    var jmDownArea = $(".mScrollDownArea");
    var mousedownEventObject = null;

    var init = function() {
        repaintButton();
        doScroll(0);
        jmButton.mousedown(function(e) {
            mousedownEventObject = e;
            e.stopPropagation();
            return false;
        });
        jmScroll.mousewheel(function(event, delta) {
            doScroll(-delta * 2);
            return true;
        });
        $("*").mousemove(function(e) {
            if (mousedownEventObject != null) {
                e.stopPropagation();
                doScroll(e.pageY - mousedownEventObject.pageY);
                mousedownEventObject = e;
                return false;
            }
        }).mouseup(function(e) {
            mousedownEventObject = null;
        });

        jmDownArea.click(function() {
            doScroll(jmButton.height());
        });
        jmUpArea.click(function() {
            doScroll(-jmButton.height());
        });
    }

    var doScroll = function(diffPx) {
        var top = trimPxToInt(jmButton.css("top")) + diffPx;


        if (diffPx < 0) {
            if (top < 0) top = 0;
        } else if (diffPx > 0) {
            if (top + jmButton.height() >= jmScroll.height()) top = jmScroll.height() - jmButton.height();
        }
        jmButton.css("top", top + "px");
        jmUpArea.css("height", top + "px");
        jmDownArea.css("top", top + jmButton.height() + "px").css("height", jmScroll.height() - top - jmButton.height() + "px");
        fireTarget();
    }

    var fireTarget = function() {
        var rate = trimPxToInt(jmButton.css("top")) / jmScroll.height();
        jTarget.scrollTop(Math.floor(jTarget.get(0).scrollHeight * rate));
    }

    var repaintButton = function() {
        var buttonHeight = calcButtonHeight();
        var buttonHeightMin = jmButtonTop.height() + jmButtonBottom.height() + 10;
        var buttonMiddleHeight;
        if (buttonHeight < buttonHeightMin) {
            buttonHeight = buttonHeightMin;
            buttonMiddleHeight = 10;
        } else {
            buttonMiddleHeight = buttonHeight - (jmButtonTop.height() + jmButtonBottom.height());
        }
        jmButton.css("height", buttonHeight + "px");
        jmButtonMiddle.css("top", jmButtonTop.height() +  "px")
                      .css("height", buttonMiddleHeight +  "px");
        jmButtonBottom.css("top", jmButtonTop.height() + buttonMiddleHeight + "px");
        jmButton.css("top", calcButtonTop() + "px");
    }

    var calcButtonHeight = function() {
        return Math.floor(getRate() * jmScroll.height());
    }

    var calcButtonTop = function() {
        if (getRate() == 1) return 0;
        else return Math.floor(jTarget.scrollTop() / jTarget.get(0).scrollHeight * jmScroll.height());
    }

    var getRate = function() {
        //var r = jmScroll.height() / jTarget.get(0).scrollHeight;
        r = jTarget.height() / jTarget.get(0).scrollHeight;
        return (r > 1) ? 1 : r;
    }

    this.repaint = function() {
        repaintButton();
    }

    init();
}