/** 
 * ui.js
 * Hiper Ochinchin Time Simulator 
 * Author: at-akada
 * nightly[atmark]at-akada.org
 * 2008.02.28-
 *
 */


var UI = new Class();
Class.extend(UI,{
    'initialize': function(){
        Component.initialize();
        this.initEvents();
    },
    'initEvents': function(){
        this.startEvent = [$('startButton'),'click',Function.bind(this.startSimulation,this)];
        this.stopEvent = [this.startEvent[0],'click',Function.bind(this.stopSimulation,this)];
        setEvent.apply(null,this.startEvent);
        this.config = $('config');
        setEvent(this.config,'submit',Function.bind(Form.onSubmit,Form));
        setEvent($('defaultSetting'),'click',
                 Function.bind(this.defaultSetting,this));
        var inputs = this.config.getElementsByTagName('input');
        for(var i=0,l=inputs.length;i<l;i++){
            if(inputs[i].type == "text"){
                var _this_ = this;
                var handle = Function.curry(function(input,e){
                    Form.checkAndSync(input,e);
                },inputs[i])
                setEvent(inputs[i],'change',handle);
            }
            if(inputs[i].id == "antiAgent_amount"){
                setEvent(inputs[i],'change',Form.updateAmount);
            }
        }
    },
    'defaultSetting': function(){
        Object.recursiveExtend(Config,Default);
        Form.syncToConfig();
        Cookie.deleteAll();
        this.stopSimulation();
        Component.show('初期設定に戻しました');
    },
    'buttonOpen': function(){
        removeEvent.apply(null,UI.stopEvent);
        setEvent.apply(null,UI.startEvent);
        this.startEvent[0].value = "シミュレーション開始";
    },
    'buttonClose': function(){
        removeEvent.apply(null,this.startEvent);
        var button = this.startEvent[0];
        button.value = "シミュレーション停止";
        setEvent.apply(null,this.stopEvent);
    },
    'startSimulation': function(){
        this.buttonClose();
        if(!Simulator.instance.running);
        Simulator.instance.start();
    },
    'stopSimulation': function(){
        this.buttonOpen();
        if(Simulator.instance.running);
        Simulator.instance.stop();
    }
});
var Component = new Class();
Class.extend(Component,{
    'initialize': function(){
        this.dialog = Component.makeDialog('メッセージ','dialog');
        this.error = Component.makeDialog('エラー','error');
        this.error.input = {};
        this.tip = Component.makeTooltip();
    },
    'makeDialog': function(title,type){
        var dialog = {};
        dialog.html = HTML.create('div',{'id': type},
                                  HTML.create('h3',null, 
                                              HTML.create('#text',title)
                                             ));
        dialog.text = HTML.create('div',{'id': type + 'Text'});
        var ok = HTML.create('input',{'type':'button',
            'id': 'ok',  'name': 'ok',  'value': 'OK'
            });
        dialog.ok = ok;
        var div = HTML.create('div',{'id': type + 'Body'},
            dialog.text,  ok);
        dialog.html.style.display = "none";
        dialog.html.appendChild(div);
        var _this_ = this;
        var hide = function(){_this_.hide(type)};
        setEvent(dialog.html,'click',hide);
        setEvent(dialog.ok, 'click',hide);
        document.body.appendChild(dialog.html);
        return dialog;
    },
    'show': function(msg,type,input){
        var type = type || 'dialog';
        this[type].html.style.display = '';
        this[type].text.innerHTML = msg;
        this[type].display = true;
        if(input){
            this[type].input.html = input;
            input.style.backgroundColor = "#AA5050";
            this[type].input.flag = true;
        }
    }, 
    'hide': function(type){
        var type = type || 'dialog';
        if(!this[type])return;
        this[type].html.style.display = 'none';
        this[type].display = false;
        if(type == "error" && this[type].input.flag)
            this[type].input.html.style.backgroundColor = "";
    },
    'makeTooltip': function(width){
        var w = width || 80;
        var tip = HTML.create('div', {'className': 'tooltip'});
        tip.style.width = w + "px";
        tip.style.display = "none";
        document.body.appendChild(tip);
        return tip;
    },
    'setOpacity': function(target,opac){
        var style = target.style;
        if(ua.ie)
            style.filter = 'alpha(opacity='+opac*10+')';
        else{
            style.MozOpacity = opac/10;
            style.opacity = opac/10;
        }
    },
    'fadeout': function(target){
        var c = 10;
        var _this_ = this;
        var loop = setInterval(function(){
            c--;
            _this_.setOpacity(target,c);
            if(c == 0){
                clearInterval(loop);
                target.style.display = "none";
                _this_.setOpacity(target,10);
            }
        },50);
    },
    'tooltip': function(msg,x,y){
        var x = x || ua.ie ? document.documentElement.scrollLeft : window.pageXOffset;
        var y = y || ua.ie ? document.documentElement.scrollTop : window.pageYOffset;
        this.tip.style.display = "";
        this.tip.innerHTML = msg;
        this.tip.style.left = x + "px";
        this.tip.style.top = y + "px";
        var _this_ = this;
        setTimeout(function(){
            _this_.fadeout(_this_.tip);
        },100);
    }
});


var Form = new Class();
Class.extend(Form,{
    'initialize': function(painter){
        this.painter = painter;
        this.ui = painter.ui;
        this.form = $('config');
        var inputs = this.form.getElementsByTagName('input');
        this.inputs = [];
        for(var i=0,l= inputs.length;i<l;i++){
            if(inputs[i].type == "text")
                this.inputs.push(inputs[i]);
        }
        this.loadCookie();
    },
    'foreach': function(itr,binding){
        var binding = binding || null;
        var inputs = this.inputs;
        for(var i=0,l=inputs.length;i<l;i++){
            itr.apply(binding,[inputs[i],i,l]);
        }
    },
    'loadCookie': function(){
        var keys = [];
        this.foreach(function(i){
            keys.push(i.name);
        });
        var c = Cookie.getHash(keys);
        for(key in c){
            this.form[key].value = c[key];
            if(this.form[key].type=="text")
                Form.checkAndSync(this.form[key]);
        }
    },
    'checkNumbers': function(input,max){
        var str = input.value;
        if(str == "")
            return null;
        var r = /^[0-9]+$/.test(str);
        if(!r){
            Component.show("半角数字以外の記号を入力しないで下さい。",'error',input);
            return r;
        }
        if(r && max && str > max){
            Component.show("0から" + max + "までの数字を入力して下さい。",'error',input);
            r = false;
        }
        return r;        
    },
    'updateAmount': function(input){
        $('cooperateAgent_amount').value = 10 - this.form.antiAgent_amount.value;
    },
    'syncToConfig': function(){
        Form.foreach(function(input){
            if(input.name.indexOf("_") > 0){
                var key = input.name.split("_");
                input.value = Config[key[0]][key[1]];
            }
            else
                input.value = Config[input.name];
        });
    },
    'setDefault': function(input){
        if(input.name.indexOf("_") > -1){
            var key = input.name.split("_");
            Config[key[0]][key[1]] = Default[key[0]][key[1]];
            input.value = Default[key[0]][key[1]];
        }else{
            var name = input.name;
            Config[name] = Default[name];
            input.value = Default[name];
        }
        return true;
    },
    'checkAndSync': function(input){
        Component.hide('error');
        Component.hide('dialog');
        var name = input.name;
        var flag = true;
        if(input.value == "")
            return this.setDefault(input);
        if(name == "amountOfAgent" || name == "baseInterval"){
            flag = this.checkNumbers(input);
            if(!flag){
                    return flag;
            }else{
                Config[name] = input.value;
            }
        }else if(name == "antiAgent_amount" || name == "antiAgent_frequent"
           || name == "cooperateAgent_amount" || name == "cooperateAgent_frequent"
                 || name== "appendProbability"){
            var key = name.split("_");
            flag = this.checkNumbers(input,10); 
            if(!flag)return flag;
            else{
                Config[key[0]][key[1]] = input.value;
            }
        }
        else{
            Config[name] = input.value;
        }
        if(flag){
            if(Component.tip)
                Component.tooltip("変更を反映");
            Cookie.setCookie(input.name,input.value);
        }
        return flag;
    },
    'onSubmit': function(e){
        if(ua.ie)
            window.event.returnValue = false;
        else if(e.preventDefault)
            e.preventDefault();
        var inputs = this.form.getElementsByTagName('input');
        var flag = true;
        var pairs = [];
        for(var i=0,l=inputs.length;i<l;i++){
            if(inputs[i].type=="text"){
                flag = Form.checkAndSync(inputs[i]);
                if(flag){
                    var value = 
                        inputs[i].name=="word" || inputs[i].name=="whenComplete" ?
                        encodeURIComponent(inputs[i].value)
                        : inputs[i].value;
                    pairs.push(inputs[i].name+"="+value);
                }
            }if(!flag)
                return false;
        }
        if(Simulator.instance.running)
            UI.stopSimulation();
        var url = location.protocol + "//" + location.host + location.pathname + "?" + pairs.join("&");
        Component.show("設定を完了しました。<br />以下のURLにアクセスすることで再びこの設定を読み込むことができます。<br />" +"<a href=\""+url+"\">"+url+"</a>");
    }
});
