/*  "escapeHTML", "$A" and "bind" in prototype.js 1.5.0
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the Prototype web site: http://prototype.conio.net/ 
 */

String.prototype.escapeHTML = function() {
    var div = document.createElement('div');
    var text = document.createTextNode(this);
    div.appendChild(text);
    return div.innerHTML;
}

var $A = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0, length = iterable.length; i < length; i++)
      results.push(iterable[i]);
    return results;
  }
}

Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}

function createXmlHttp() {
    if (window.XMLHttpRequest) {
        return new XMLHttpRequest();
    } else if (window.ActiveXObject) {
        try {
            return new ActiveXObject("Msxml2.XMLHTTP");
        } catch(e) {
            return new ActiveXObject("Microsoft.XMLHTTP");
        }
    } else {
        return null;
    }
}


var Quiz = function()
{
    this.q   = document.getElementById('questioner');
    this.msg = document.getElementById('msg');
    this.a   = document.getElementById('panelist');
    this.al  = document.getElementById('answer_list');
    this.s   = document.getElementById('start');

    this.s.onclick = this.run.bind(this);

    this.op  = [];

    for(var i = 1; i <= 8; i+=i) {
        var li = document.createElement('LI');
        li.id = 'option_' + i;
        li.onmouseover = function(){ this.className = 'hover'; };
        li.onmouseout = function(){ this.className = ''; };
        li.onclick = this._answer(this);
        this.al.appendChild(li);
        this.op[i] = li;
    }

    this.nextButton = document.getElementById('next_button');
    this.nextButton.onclick = this._nextButton(this);
}

Quiz.prototype =
{
    data: null,
    question: {},
    pointer: 0,
    answered: true,
    correct: 0,
    mode: 'play',

    dec: function(str)
    {
        return (this.mode == 'edit') ? decodeURIComponent(str) : str;
    },

    load: function(key, pass, callback)
    {
        var xmlhttp = createXmlHttp();

        if (xmlhttp == null) {
            alert('この環境ではご利用いただけません。');
        }
        
        xmlhttp.onreadystatechange = stateChange(xmlhttp, this);

        function stateChange(xhr, quiz) {
            return function() {
                if (xhr.readyState == 4) {
                    if (xhr.status == 200) {
                        if(xhr.responseText != 'error') {
                            var data = xhr.responseText.split("\n");
                            if(data[0] == '') data[0] = 'default.png';
                            quiz.q.style.backgroundImage = 'url("/resources/images/chars/' + data[0] + '")';
                            quiz.a.style.backgroundImage = 'url("/resources/images/chars/' + data[0] + '")';
                            quiz.setJson(data[1]);
                            if(quiz.mode == 'play') quiz.reset();
                            if(callback) callback();
                        } else {
                            if(quiz.mode == 'play')
                                quiz.showMsg("このクイズは削除されたか、パスワードが違います。");
                            else
                                quiz.showMsg("このクイズは削除されたか、エラーが発生しました。\n再度お試しいただくか、管理者にお知らせ下さい。");
                        }
                    } else {
                        quiz.showMsg('サーバーがビジー状態です。時間をおいてお試しください。');
                    }
                }
            }
        }

        var action = (this.mode == 'play') ? '/load?key=' + key : '/load?key=' + key + '&pass=' + pass;

        xmlhttp.open('get', action, true);
        xmlhttp.send(null);
    },

    setJson: function(json)
    {
        this.data = json.parseJSON();
    },

    run: function()
    {
        this.closeAds();
        this.s.style.display = 'none';
        if(this.data.o != '') {
            this.showMsg(this.dec(this.data.o), this.showNextButton);
        } else {
            this.display();
        }
    },

    reset: function()
    {
        this.question = {};
        this.pointer = 0;
        this.correct = 0;
        this.nextProcess = this._nextProcessDisplay;
        this.msg.innerHTML = '<strong>' + this.dec(this.data.t) + '</strong><br />' + this.dec(this.data.a).replace(/\n/g, '<br />').replace(/(https?:\/\/[0-9a-zA-Z./+%:~\-_?&#,=]+)/g, '<a href="$1" target="_blank">$1</a>');
        for(var i = 1, j = 1; i <= 8; i+=i) {
            this.op[i].innerHTML = '';
            this.op[i].style.display = 'none';
        }
        this.q.style.backgroundPosition = "0 0";
        this.a.style.backgroundPosition = "0 -96px";
        this.s.style.display = 'inline';
    },

    display: function()
    {
        if(this.hasNext()) {
            this.question = this.next();
            this.showMsg(this.dec(this.question.q), this.prepareSelector);
        } else {
            this.clearSelector();
            if(this.data.b.match(/^[0-9]+$/)) {
                if(this.correct >= parseInt(this.data.b)) {
                    if(this.data.p != '') this.showMsg(this.dec(this.data.p), this.showNextButton);
                } else {
                    if(this.data.f != '') this.showMsg(this.dec(this.data.f), this.showNextButton);
                }
            }
            if(this.data.e != '')
                this.showMsg(this.dec(this.data.e), this.ending);
            else
                this.ending();
        }
    },

    ending: function()
    {
        this.nextProcess = this._nextProcessRetry;
        this.showNextButton();
    },

    hasNext: function()
    {
        return (this.data.q[this.pointer]) ? true : false;
    },

    next: function()
    {
        return this.data.q[this.pointer++];
    },

    _msgQueue:[],
    msgOnAir: false,
    showMsg: function(text, callback)
    {
        if(this.msgOnAir) {
            this._msgQueue.push(arguments);
            return;
        }

        this.msgOnAir = true;

        if(callback) callback = callback.bind(this);

        this.msg.innerHTML = '';

        if(!text || text == '') {
            if(callback) callback();
            this.msgOnAir = false;
            return;
        }

        var chr = text.split('');
        var pointer = 0;
        var quiz = this;

        var effect = setInterval(function(){

            if(text.substr(pointer, 6) == '<br />') {
                quiz.msg.innerHTML += '<br />';
                pointer += 5;
            } else {
                quiz.msg.innerHTML += chr[pointer].replace('<', '&lt;');
            }

            if(!chr[++pointer]) {
                clearInterval(effect);
                if(callback) callback();
                quiz.msgOnAir = false;
                if(quiz._msgQueue.length != 0) {
                    quiz.nextProcess = quiz._nextProcessMsg;
                }
            }

        }, 10);
    },

    prepareSelector: function()
    {
        for(var i = 1, j = 1; i <= 8; i+=i) {
            if(this.question['o' + j] != '') {
                this.op[i].innerHTML = '<div>' + this.dec(this.question['o' + j]).escapeHTML() + '</div>';
                this.op[i].style.display = 'block';
            } else {
                this.op[i].style.display = 'none';
            }
            j++;
        }

        this.answered = false;
    },

    clearSelector: function()
    {
        for(var i = 1; i <= 8; i+=i) this.op[i].style.display = 'none';
    },

    answer: function(option)
    {
        this.answered = true;

        if(this.question.a == option.id.substr(7)) {
            this.correct++;
            this.q.style.backgroundPosition = "-128px 0";
            this.a.style.backgroundPosition = "-128px -96px";
            this.showMsg(this.dec(this.question.c), this.showNextButton);
        } else {
            this.q.style.backgroundPosition = "-256px 0";
            this.a.style.backgroundPosition = "-256px -96px";
            this.showMsg(this.dec(this.question.m), this.showNextButton);
        }

    },

    _answer: function(quiz)
    {
        return function() {
            if(!quiz.answered) quiz.answer(this);
        }
    },

    showNextButton: function()
    {
        this.nextButton.style.display = 'inline';
    },

    hideNextButton: function()
    {
        this.nextButton.style.display = 'none';
    },

    _nextButton: function(quiz)
    {
        return function() {
            this.style.display = 'none';
            quiz.nextProcess();
        }
    },

    nextProcess: function(){},

    _nextProcessDisplay: function()
    {
        this.q.style.backgroundPosition = "0 0";
        this.a.style.backgroundPosition = "0 -96px";
        this.display();
    },

    _nextProcessMsg: function()
    {
        var m = this._msgQueue.shift();
        m[1] = m[1] || null;
        this.nextProcess = this._nextDisplay;
        this.showMsg(m[0], m[1]);
    },

    _nextProcessRetry: function()
    {
        this.reset();
        this.openAds();
    },

    openAds: function()
    {
        var ads = document.getElementById('ads');
        if(ads) ads.style.display = 'block';
    },

    closeAds: function()
    {
        var ads = document.getElementById('ads');
        if(ads) ads.style.display = 'none';
    }
}
