// -*- coding: utf-8 -*-

function addPlayer(id, src, interval, loop_def)
{
    var parent = document.getElementById("aa" + id);
    parent.appendChild(create_aaplayer(src, interval, loop_def));
}

function create_aaplayer(src, waitfor, loop)
{
    function create() {
        var player = document.createElement("div");
        player.className = "player";

        player.appendChild(create_togglebutton("連続表示", "連続表示",
                                               on_show_player));

        var panel = create_aadataplayer(src, waitfor, false, loop);
        panel.className = "panel";
        panel.style.display = "none";
        panel.oncloseclicked = panel_oncloseclicked;
        player.appendChild(panel);

        return player;
    }

    function on_show_player(btn) {
        var player = btn.parentNode;

        aadata_panel(player).style.display = "block";
        aadata_panel(player).startPlay();
        btn.style.display = "none";
        btn.setToggleState(false);

        if(player.scrollIntoView) {
            player.scrollIntoView();
        }
    }

    function panel_oncloseclicked() {
        var player = this.parentNode;

        aadata_panel(player).style.display = "none";
        aadata_panel(player).stopPlay();
        showpanel_button(player).style.display = "inline";
    }

    function showpanel_button(player) {
        return player.childNodes.item(0);
    }

    function aadata_panel(player) {
        return player.childNodes.item(1);
    }

    return create();
}

function create_aadataplayer(src, waitfor, autostart, loop)
{
    function create() {
        var panel = document.createElement("div");
        panel.className = "aadataplayer";

        var oppanel = create_oppanel();
        oppanel.setTotalStep(src.length);
        oppanel.setCurrentStep(1);
        oppanel.setSpeed(waitfor);
        oppanel.setLoop(loop);
        panel.appendChild(oppanel);

        var txtpanel = create_txtpanel();
        panel.appendChild(txtpanel);

        var datasrc = create_datasrc(src);
        panel.appendChild(datasrc);

        if(datasrc.getMaxWidth() > 0) {
            txtpanel.style.width = datasrc.getMaxWidth() + "px";
        }
        if(datasrc.getMaxHeight() > 0) {
            txtpanel.style.height = datasrc.getMaxHeight() + "px";
        }
        txtpanel.copyContent(datasrc.getSrc(0));
        oppanel.oncloseclicked = oppanel_oncloseclicked;
        oppanel.onstepchanged = oppanel_onstepchanged;

        if(autostart) {
            oppanel.startPlay();
        }

        // method
        panel.startPlay = panel_startplay;
        panel.stopPlay = panel_stopplay;

        // event
        panel.oncloseclicked = null;

        return panel;
    }

    function oppanel_oncloseclicked() {
        var panel = this.parentNode;
        invoke_oncloseclicked(panel);
    }

    function oppanel_onstepchanged(step) {
        var panel = this.parentNode;
        txtpanel(panel).copyContent(datasrc(panel).getSrc(step - 1));
    }

    function oppanel(panel) {
        return panel.childNodes.item(0);
    }

    function txtpanel(panel) {
        return panel.childNodes.item(1);
    }

    function datasrc(panel) {
        return panel.childNodes.item(2);
    }

    function panel_startplay() {
        oppanel(this).startPlay();
    }

    function panel_stopplay() {
        oppanel(this).stopPlay();
    }

    function invoke_oncloseclicked(panel) {
        if(panel.oncloseclicked) {
            panel.oncloseclicked();
        }
    }

    return create();
}

function create_oppanel()
{
    function create() {
        var panel = document.createElement("div");
        panel.className = "oppanel";

        var btnbar = document.createElement("div");
        btnbar.className = "buttonbar";

        var closebtn = create_togglebutton("×", "閉じる",
                                           closebtn_oncloseclick);
        btnbar.appendChild(closebtn);

        var playbtn = create_togglebutton("l＞", "再生/停止",
                                          playbtn_onplayclick);
        btnbar.appendChild(playbtn);

        var stepcount = create_stepcount();
        stepcount.onvaluechanged = stepcount_onstepchanged;
        stepcount.onstepclick = stepcount_onstepclick;
        btnbar.appendChild(stepcount);

        var stepspeed = create_stepspeed();
        stepspeed.onvaluechanged = stepspeed_onvaluechanged;
        btnbar.appendChild(stepspeed);

        var loopselect = create_loopselect();
        loopselect.onvaluechanged = loopselect_onvaluechanged;
        btnbar.appendChild(loopselect);

        panel.appendChild(btnbar);

        var progressbar = create_progressbar();
        panel.appendChild(progressbar);

        // method
        panel.setCurrentStep = panel_setcurstep;
        panel.setTotalStep = panel_settotalstep;
        panel.setSpeed = panel_setspeed;
        panel.setLoop = panel_setloop;
        panel.stopPlay = panel_stopplay;
        panel.startPlay = panel_startplay;

        // event
        panel.oncloseclicked = null;
        panel.onstepchanged = null;

        return panel;
    }

    function closebtn_oncloseclick(btn) {
        var panel = btn.parentNode.parentNode;
        invoke_oncloseclicked(panel);
        btn.setToggleState(false);
    }

    function playbtn_onplayclick(btn) {
        var panel = btn.parentNode.parentNode;
        var pressed = btn.isPressed();
        panel.stopPlay();
        btn.setToggleState(false);
        if(pressed) {
            btn.setToggleState(true);
            panel.startPlay();
        }
    }

    function stepcount_onstepchanged(cur, total) {
        var panel = this.parentNode.parentNode;
        panel.setTotalStep(total);
        panel.setCurrentStep(cur);
    }

    function stepcount_onstepclick() {
        var panel = this.parentNode.parentNode;
        panel.stopPlay();
    }

    function stepspeed_onvaluechanged(speed) {
        needreset = true;
    }

    function loopselect_onvaluechanged(isloop) {
        needreset = true;
    }

    function panel_setcurstep(curstep) {
        stepcount(this).setCurrentStep(curstep);
        progressbar(this).setValue(curstep);
        invoke_onstepchanged(this, curstep);
    }

    function panel_settotalstep(totalstep) {
        stepcount(this).setTotalStep(totalstep);
        progressbar(this).setRange(1, totalstep);
    }

    function panel_setspeed(speed) {
        stepspeed(this).setSpeed(speed);
    }

    function panel_setloop(isloop) {
        loopselect(this).setLoop(isloop);
    }

    function invoke_oncloseclicked(panel) {
        if(panel.oncloseclicked) {
            panel.oncloseclicked();
        }
    }

    function invoke_onstepchanged(panel, curstep) {
        if(panel.onstepchanged) {
            panel.onstepchanged(curstep);
        }
    }

    var timerid = null;
    var needreset = false;

    function panel_stopplay() {
        if(! timerid) {
            return;
        }

        window.clearInterval(timerid);
        timerid = null;
        playbtn(this).setToggleState(false);
    }

    function panel_startplay() {
        if(timerid) {
            return;
        }

        if(stepcount(this).getCurrentStep() == stepcount(this).getTotalStep()) {
            stepcount(this).setCurrentStep(1);
        }

        playbtn(this).setToggleState(true);
        needreset = false;

        var panel = this;
        timerid = window.setInterval(
            function() {
                var cur = stepcount(panel).getCurrentStep();
                var total = stepcount(panel).getTotalStep();
                if(cur < total) {
                    stepcount(panel).setCurrentStep(cur + 1);
                }
                else if(loopselect(panel).getLoop()) {
                    stepcount(panel).setCurrentStep(1);
                }
                else {
                    panel.stopPlay();
                    return;
                }

                if(needreset) {
                    panel.stopPlay();
                    panel.startPlay();
                }
            }, stepspeed(this).getSpeed());
    }

    function closebtn(panel) {
        return panel.childNodes.item(0).childNodes.item(0);
    }

    function playbtn(panel) {
        return panel.childNodes.item(0).childNodes.item(1);
    }

    function stepcount(panel) {
        return panel.childNodes.item(0).childNodes.item(2);
    }

    function stepspeed(panel) {
        return panel.childNodes.item(0).childNodes.item(3);
    }

    function loopselect(panel) {
        return panel.childNodes.item(0).childNodes.item(4);
    }

    function progressbar(panel) {
        return panel.childNodes.item(1);
    }

    return create();
}

function create_togglebutton(text, title, onclick)
{
    var ispressed = false;

    function create() {
        var btn = document.createElement("input");
        btn.type = "button";
        btn.className = "button";
        btn.value = text;
        btn.title = title;
        btn.onclick = btn_onclick;

        // method
        btn.isPressed = getstate;
        btn.setToggleState = setstate;

        return btn;
    }

    function setstate(pressed) {
        ispressed = pressed;

        if(ispressed) {
            this.className = "button pressed";
        }
        else {
            this.className = "button";
        }
    }

    function getstate() {
        return ispressed;
    }

    function btn_onclick() {
        this.setToggleState(! ispressed);
        onclick(this);
    }

    return create();
}

function create_stepcount()
{
    var current = 1;
    var total = 1;

    function create() {
        var panel = document.createElement("span");
        panel.className = "counter";

        var step = document.createElement("input");
        step.type = "text";
        step.className = "step";
        step.readOnly = true;
        panel.appendChild(step);

        panel.appendChild(create_togglebutton("||＜", "1コマ前",
                                              prevbtn_onclick));

        panel.appendChild(create_togglebutton("＞||", "1コマ後",
                                              nextbtn_onclick));

        // method
        panel.setCurrentStep = setcurstep;
        panel.getCurrentStep = getcurstep;
        panel.setTotalStep = settotalstep;
        panel.getTotalStep = gettotalstep;

        // event
        panel.onvaluechanged = null;
        panel.onstepclick = null;

        return panel;
    }

    function prevbtn_onclick(btn) {
        var cur = current - 1;
        if(cur < 1) {
            cur = 1;
        }

        var panel = btn.parentNode;
        panel.setCurrentStep(cur);
        btn.setToggleState(false);
        invoke_onstepclick(panel);
    }

    function nextbtn_onclick(btn) {
        var cur = current + 1;
        if(cur > total) {
            cur = total;
        }

        var panel = btn.parentNode;
        panel.setCurrentStep(cur);
        btn.setToggleState(false);
        invoke_onstepclick(panel);
    }

    function setcurstep(num) {
        if(num == current) {
            return;
        }
        current = num;
        update_step(this);
        invoke_onvaluechanged(this);
    }

    function getcurstep() {
        return current;
    }

    function settotalstep(num) {
        if(num == total) {
            return;
        }
        total = num;
        update_step(this);
        invoke_onvaluechanged(this);
    }

    function gettotalstep() {
        return total;
    }

    function update_step(panel) {
        step(panel).value = current + " / " + total;
    }

    function step(panel) {
        return panel.childNodes.item(0);
    }

    function invoke_onvaluechanged(panel) {
        if(panel.onvaluechanged) {
            panel.onvaluechanged(current, total);
        }
    }

    function invoke_onstepclick(panel) {
        if(panel.onstepclick) {
            panel.onstepclick()
        }
    }

    return create();
}

function create_stepspeed()
{
    var speedmsec = 0;

    function create() {
        var panel = document.createElement("span");
        panel.className = "speed";

        var speedval = document.createElement("input");
        speedval.type = "text";
        speedval.className = "speedval";
        speedval.readOnly = true;
        panel.appendChild(speedval);

        panel.appendChild(create_togglebutton("−", "速くする",
                                              decbtn_onclick));

        panel.appendChild(create_togglebutton("＋", "遅くする",
                                              incbtn_onclick));

        // method
        panel.setSpeed = setspeed;
        panel.getSpeed = getspeed;

        // event
        panel.onvaluechanged = null;

        return panel;
    }

    function decbtn_onclick(btn) {
        var num = speedmsec;
        num -= getrangeincval(num - 1);
        var panel = btn.parentNode;
        panel.setSpeed(num);
        btn.setToggleState(false);
    }

    function incbtn_onclick(btn) {
        var num = speedmsec;
        num += getrangeincval(num);
        var panel = btn.parentNode;
        panel.setSpeed(num);
        btn.setToggleState(false);
    }

    function setspeed(num) {
        if(num < 10) {
            num = 10;
        }

        if(num == speedmsec) {
            return;
        }
        speedmsec = num;

        if(num <= 500) {
            speedval(this).value = num + " ms";
        }
        else {
            speedval(this).value = (num / 1000).toFixed(1) + " s";
        }

        invoke_onvaluechanged(this);
    }

    function getspeed() {
        return speedmsec;
    }

    function speedval(panel) {
        return panel.childNodes.item(0);
    }

    function invoke_onvaluechanged(panel) {
        if(panel.onvaluechanged) {
            panel.onvaluechanged(speedmsec);
        }
    }

    var ranges = [
        [  100,  10 ],
        [  500,  50 ],
        [ 1500, 100 ],
        [ 5000, 500 ]
        ];
    function getrangeincval(num) {
        var i;
        for(i = 0; i < ranges.length; i++) {
            if(num < ranges[i][0]) {
                return ranges[i][1];
            }
        }
        return 1000;
    }

    return create();
}

function create_loopselect()
{
    var isloop = false;

    function create() {        
        var panel = document.createElement("span");
        panel.className = "loop";

        var check = document.createElement("input");
        check.type = "checkbox";
        check.title = "チェックをつけるとループする";
        check.checked = isloop;
        check.onclick = check_onclick;
        panel.appendChild(check);

        panel.appendChild(document.createTextNode("リピート"));

        // method
        panel.setLoop = setloop;
        panel.getLoop = getloop;

        // event
        panel.onvaluechanged = null;

        return panel;
    }

    function check_onclick() {
        var panel = this.parentNode;
        panel.setLoop(this.checked);
    }

    function setloop(val) {
        if(val == isloop) {
            return;
        }
        isloop = val;
        loop(this).checked = isloop;
        invoke_onvaluechanged(this);
    }

    function getloop() {
        return isloop;
    }

    function loop(panel) {
        return panel.childNodes.item(0);
    }

    function invoke_onvaluechanged(panel) {
        if(panel.onvaluechanged) {
            panel.onvaluechanged(isloop);
        }
    }

    return create();
}

function create_progressbar()
{
    var value = 1;
    var min = 1;
    var max = 1;

    function create() {
        var panel = document.createElement("div");
        panel.className = "progressbar";

        var filler = document.createElement("div");
        filler.className = "filler";
        panel.appendChild(filler);

        // method
        panel.setValue = setvalue;
        panel.setRange = setrange;

        return panel;
    }

    function setvalue(val) {
        value = val;
        updatefiller(this);
    }

    function setrange(v1, v2) {
        min = v1;
        max = v2;
        updatefiller(this);
    }

    function getfiller(panel) {
        return panel.childNodes.item(0);
    }

    function updatefiller(panel) {
        getfiller(panel).style.width =
            (100 * (value - min) / (max - min)) + "%";
    }

    return create();
}

function create_txtpanel()
{
    function create() {
        var panel = document.createElement("div");
        panel.className = "txtpanel";

        panel.appendChild(document.createElement("div"));

        // method
        panel.copyContent = settext;

        return panel;
    }

    function settext(src) {
        var newtext = src.cloneNode(true);
        newtext.style.display = "block";
        this.replaceChild(newtext, gettext(this));
    }

    function gettext(panel) {
        return panel.childNodes.item(0);
    }

    return create();
}

function create_datasrc(src)
{
    var maxw = 0;
    var maxh = 0;

    function create() {
        var panel = document.createElement("div");
        panel.className = "datasrc";

        var i;
        for(i = 0; i < src.length; i++) {
            var d = src[i];

            if(d.scrollWidth > maxw) {
                maxw = d.scrollWidth;
            }
            if(d.scrollHeight > maxh) {
                maxh = d.scrollHeight;
            }
        }

        // method
        panel.getSrc = getsrc;
        panel.getMaxWidth = getmaxwidth;
        panel.getMaxHeight = getmaxheight;

        return panel;
    }

    function getsrc(idx) {
        return src[idx];
    }

    function getmaxwidth() {
        return maxw;
    }

    function getmaxheight() {
        return maxh;
    }

    return create();
}

function gensrc(from, to)
{
    var src = new Array(to - from + 1), i;
    for(i  = from; i <= to; i++) {
        src[i - from] = document.getElementById("aab" + i);
    }
    return src;
}

function gensrc_fromdata(data, appendid)
{
    var appendto = document.getElementById("aa" + appendid);
    var src = new Array(data.length), i;
    for(i = 0; i < data.length; i++) {
        var d = document.createElement("div");
        d.className = "aa";
        d.style.display = "none";
        d.innerHTML = data[i];
        appendto.appendChild(d);

        src[i] = d;
    }

    return src;
}

