String.prototype.trim = function(){
	return this.replace(/^\s+|\s+$/g, "");
};

String.prototype.fromDashedToCamel = function(){
    var s = this.replace(/\W+(.)/g, function (x, chr) {return chr.toUpperCase();});
    s = s[0].toUpperCase() + s.slice(1);
    return s;
};

String.prototype.fromCamelToDashed = function(){
    return this.replace(/\W+/g, '-').replace(/([a-z\d])([A-Z])/g, '$1-$2').toLowerCase();
};

var Util = {
    dims:{
        width: $(window).width(),
        height: $(window).height()
    },
    getMrtMask: function(){
        if($('#mrtMask').length<=0){
            $(document.body).append('<div id="mrtMask"></div>');
        }
        return {
            color:$('#mrtMask').css('backgroundColor'),
            opacity:$('#mrtMask').css('opacity')
        };
    },
    mrTOptions:{
        top:10,
        closeOnClick:false,
        mask:{
            color:"#fff",
            opacity:0
        },
        speed:200,
        load: true
    },
    mrTPageSource:null,
    sprintf:function(){
        if( Util.sprintf.arguments.length < 2 ) {
            return;
        }

        var data = Util.sprintf.arguments[ 0 ];

        for( var k=1; k<Util.sprintf.arguments.length; ++k ) {

            switch( typeof( Util.sprintf.arguments[ k ] ) )
            {
                case 'string':
                    data = data.replace( /%s/, Util.sprintf.arguments[ k ] );
                    break;
                case 'number':
                    data = data.replace( /%d/, Util.sprintf.arguments[ k ] );
                break;
                case 'boolean':
                    data = data.replace( /%b/, Util.sprintf.arguments[ k ] ? 'true' : 'false' );
                break;
                default:
                    /// function | object | undefined
                break;
            }
        }
        return( data );
    },
    showLoader:function(){
        if($("#Loader").length==0){
            $('<div id="Loader"></div>').appendTo(document.body);
        }
        $("#Loader").css("left",((this.dims.width-parseInt($("#Loader").css("width")))/2) + "px");
        $("#Loader").css("top",((this.dims.height-parseInt($("#Loader").css("height")))/2) + "px");
        $("#Loader").fadeIn(200);
    },
    hideLoader:function(){
        $("#Loader").fadeOut(200);
        setTimeout(function(){$("#Loader").remove()},200);
    },
    showInfoBox:function(p){
        var cssClass="Error";
        if(p.type=="e"){
            cssClass="Error";
        }else if(p.type=="i"){
            cssClass="Info";
        }else if(p.type=="s"){
            cssClass="Success";
        }else if(p.type=="w"){
            cssClass="Warning";
        }
        $('<div id="InfoBox" class="'+cssClass+'"><div id="InfoBoxMessage">'+p.m+'<div id="InfoBoxClose">&times;</div></div></div>').appendTo(document.body);
        $("#InfoBoxClose").click(function(){Util.hideInfoBox();});
        $("#InfoBox").slideDown(200);
        if(p.dur){
            setTimeout(function(){Util.hideInfoBox();},(p.dur*1000))
        }
    },
    hideInfoBox:function(){
        $("#InfoBox").slideUp(200,function(){$(this).remove();});
    },
    initMrT:function(html,opt){
        if($("#mrt").length>0){$("#mrt").remove();}
        $(html).appendTo(document.body);
        var maxH=$(window).height()-160;
        $("#mrtScrollWrap").css("max-height",maxH+"px");
        $("#mrt").draggable({handle:'.Handle'});
        var thisOpt = Util.mrTOptions;
        thisOpt.mask = Util.getMrtMask();
        if($.browser.msie){ // because of transparency
            thisOpt.speed = 0;
            thisOpt.closeSpeed = 0;
        }
        $.extend(true, thisOpt, opt);
        $("#mrt").overlay(thisOpt);
        if(Util.isIE7()) {
            var w=$('#mrt').width()-$('#mrt .mrtbt').width();
            $('#mrt .mrtbt').width(w);
            $('#mrt .mrtbb').width(w);
        }
    },
    loadMrT:function(p){
        Util.showLoader();
        $.ajax({
            url:p.url,
            cache: false,
            success: function(html){
                Util.evalResponse(html);
                Util.hideLoader();
                Util.initMrT(html,p);
                if($.isFunction(p.onLoad)){p.onLoad()}
            },
            error: function(html) {
                Util.hideLoader();
                // TODO: display error message when load fails
            }
        });
    },
    submitMrT:function(p){
        Util.showLoader();
        $.ajax({
            url:$('#'+p.formId).attr("action"),
            data:$('#'+p.formId).serialize(),
            dataType:"html",
            type:"post",
            cache: false,
            success: function(response){
                Util.evalResponse(response);
                Util.hideLoader();
                var mrt = $("#mrt").data("overlay");
                if(p.wizard){
                    if(p.lastStep) {
                        mrt.close();
                    }else{
                        Util.initMrT(response, {speed:0});
                    }
                } else {
                    try {
                        if($.parseJSON(response)) {
                            mrt.close();
                        }
                    } catch (e) {
                        Util.initMrT(response, {speed:0});
                    }
                }
                if($.isFunction(p.onFinish)){p.onFinish(response)}
            }
        });
    },
    closeMrT:function(){
        var mrt = $("#mrt").data("overlay");
        if( undefined != mrt ) {
            mrt.close();
        }
    },
    setMrTPageSource:function(pageSource){
        Util.mrTPageSource=pageSource;
    },
    getMrTPageSource:function(){
        return Util.mrTPageSource;
    },
    setSelectedScrollableNav:function(el,i){
        el.each(function(){$(this).removeClass("Selected")});
        el.eq(i+1).addClass("Selected");
    },
    evalResponse:function(r){
        try{
            if(r.code && r.code==113) {
                location.href=webroot+"/user/login/?sessionExpired=1";
            }
        } catch(e){
        }
    },
    animateCostToArea:function(area, minArea, maxArea) {
        // CostToAreaTooltipMarker
        var p=parseFloat(String(area).replace(",","."))/maxArea;
        var pMin=minArea/maxArea;
        var left=0;
        var markerOffset = 13;
        var cssProp = {left:0,right:'auto'};
        var wT = $("#CostToAreaTooltip").width();
        var w = $("#AreaMessage").width();
        var leftL = p*w-markerOffset-pMin/2*w;
        if(leftL+wT<w){
            left = leftL;
        } else {
            left = p*w-wT-1;
            if(Util.isIE7()){
                left = left+markerOffset;
            }
            cssProp = {left:'auto',right:0};
        }
        $("#CostToAreaTooltipMarker").removeClass("cBlock fl fr");
        $("#CostToAreaTooltipMarker").css(cssProp);
        $("#CostToAreaTooltip").animate({
            "left":left
        }, 700);
    },
    onloadMrt:function(callback){
        setTimeout(callback,0);
    },
    sleep:function(delay){
        Util.wait(delay);
    },
    wait:function(delay){
        var start = new Date().getTime();
        while (new Date().getTime() < start + delay);
    },
    getIdFromDomId:function(s){
        return s.substr(s.lastIndexOf('_')+1);
    },
    formatTimestamp:function(ts) {
        var now = new Date();
        var yesterday = new Date();
        yesterday.setDate( now.getDate() - 1 );
        var logTime = new Date( ts );
        var text = '';
        var format = '';
        if( now.getDate() == logTime.getDate() ) {
            text = I18n.JS_FORMAT_TIMESTAMP_TODAY + ' ';
            format = 'H:i';
        }
        else if( yesterday.getDate() == logTime.getDate() ) {
            text = I18n.JS_FORMAT_TIMESTAMP_YESTERDAY + ' ';
            format = 'H:i';
        }
        else {
            format = 'd.m. H:i';
        }
        return text + $.PHPDate( format, logTime );
    },
    isIE7:function(){
        var r=false;
        if($.browser.msie && $.browser.version=='7.0'){
            r=true;
        }
        return r;
    },
    isIE8:function(){
        var r=false;
        if($.browser.msie && $.browser.version=='8.0'){
            r=true;
        }
        return r;
    },
    getLang:function(){
        if(lang != 'undefined') {
            return lang;
        } else {
            return 'en';
        }
    },
    getTheme:function(){
        var r = 'default';
        if(typeof(Settings) != 'undefined' && typeof(Settings.theme) != 'undefined') {
            r = Settings.theme;
        }
        return r;
    },
    extend:function(subClass, superClass) {
        var F = function(){};
        F.prototype = superClass.prototype;
        subClass.prototype = new F();
        subClass.prototype.constructor = subClass;

        subClass.superclass = superClass.prototype;
        if(superClass.prototype.constructor == Object.prototype.constructor) {
            superClass.prototype.constructor = superClass;
        }
    },
    d:0
};

var Validator = {
    errorPlacement:function(error, element) {
        error.appendTo($("#"+element.attr("id")+"Errors"));
    },
    success:function(label) {
        $("#GeneralError").css("visibility","hidden");
        var elId=label.attr("for");
        $("#"+elId).removeClass("inputError");
        label.remove();
    },
    submitHandler:function(form) {
        form.submit();
    },
    getErrorElement:function(){
        return "li";
    },
    getErrorClass:function(){
        return "inputError";
    },
    create:function(formId,rules,messages){
        return $("#"+formId).validate({
            errorElement:Validator.getErrorElement(),
            errorClass:Validator.getErrorClass(),
            errorPlacement:function(error, element){Validator.errorPlacement(error, element)},
            submitHandler:function(form){Validator.submitHandler(form)},
            success:function(label){Validator.success(label)},
            rules:rules,
            messages:messages
        });
    }
};

var PVFaultAlert = {
    update:function(json) {
        json=jQuery.parseJSON(json);
        $(".js_PVFaultAlertStatus").html(json.status);
        $("#js_PVFaultAlertLimit").html(json.limit);
        $("#js_PVFaultAlertNotification").html(json.notificationTo);
        $("#js_PVFaultAlert .Wrap").show();
    }
};


var Airbag = {
    load:function(current,target,forecast,numOfSteps){
        var scale = this.calcScale(target,forecast,numOfSteps);
        var w=$("#AirbagScaleWrap").width();
        var max=0;
        var wFore="";
        var wForeLeft=0;
        var targetLeft=0;
        if(target>=forecast){
            max=current;
            max=target;
            wFore=forecast/max*w+2;
            wForeLeft=0;
            targetLeft = target/max*w-$("#AirbagTargetValWrap").width();
            $("#AirbagForecastBar").css("left",wForeLeft+"px");
            $("#AirbagForecastBar").removeClass("AirbagForecastBarOver");
            $("#AirbagForecastBar").addClass("AirbagForecastBarUnder");
            $("#ProjectedUsageValue").removeClass("ProjectedUsageValueOver");
            $("#ProjectedUsageValue").addClass("ProjectedUsageValueUnder");
            $("#AirbagForecastLegendColor").removeClass("AirbagForecastLegendColorOver");
            $("#AirbagForecastLegendColor").addClass("AirbagForecastLegendColorUnder");
        }else{
            max=forecast;
            wFore=Math.round((forecast-target)/max*w);
            wForeLeft=forecast/max*w-wFore+1;
            $("#AirbagForecastBar").css("left",wForeLeft+"px");
            $("#AirbagForecastBar").removeClass("AirbagForecastBarUnder");
            $("#AirbagForecastBar").addClass("AirbagForecastBarOver");
            $("#ProjectedUsageValue").removeClass("ProjectedUsageValueUnder");
            $("#ProjectedUsageValue").addClass("ProjectedUsageValueOver");
            $("#AirbagForecastLegendColor").removeClass("AirbagForecastLegendColorUnder");
            $("#AirbagForecastLegendColor").addClass("AirbagForecastLegendColorOver");
            targetLeft = target/max*w-$("#AirbagTargetValWrap").width();
        }
        wCur=Math.round(current/max*w);
        $("#AirbagTargetValWrap").css("left",targetLeft+"px");
        $("#AirbagForecastBar").css("width",wFore+"px");
        $(".AirbagScaleLabel").each(function(){$(this).remove()});
        $.each(scale.stepData, function(i,el){
            var style="left:"+el.left;
            $('<div id="AirbagScaleLabel_'+i+'" class="AirbagScaleLabel" style="'+style+'">'+el.label+'</div>').appendTo($("#AirbagScaleWrap"));
            if(i!=0){
                var elW=$("#AirbagScaleLabel_"+i).width();
                var left = parseInt($("#AirbagScaleLabel_"+i).css("left"));
                var newLeft = left-elW/2;
                if(i==scale.stepData.length-1){
                    if((newLeft+elW)>w){
                        newLeft=w-elW+1;
                    }
                }
                $("#AirbagScaleLabel_"+i).css("left",newLeft+"px");
            }
        })
        $("#AirbagGridBoxWrap").empty();
        for(i=0;i<scale.gridLineCount;i++){
            var cssClass="AirbagGridBox";
            if((i+1)%5==0){cssClass+=" AirbagGridBoxMajor"}
            $('<div class="'+cssClass+'" style="left:'+((i+1)*scale.gridWidthPx)+'px"></div>').appendTo($("#AirbagGridBoxWrap"));
        }
        this.animate(wCur);
    },
    calcScale:function(target,forecast,numOfSteps){
        var w=$("#AirbagScaleWrap").width();
        var stepSize=[1,2,2.5,4,5,8];
        var max=(target>=forecast)?target:forecast;
        var step = 0;
        var v=max/numOfSteps;
        var exp = -2;
        var stepFound=false;
        var minorGridLineCount = 5;
        if(max>0) {
            while(!stepFound){
                for(i=0;i<stepSize.length;i++){
                    var curStep=stepSize[i]*Math.pow(10,exp);
                    if(v<curStep){
                        var ii=(i==0)?0:i-1;
                        step=stepSize[ii]*Math.pow(10,exp);
                        stepFound = true;
                        break;
                    }
                }
                exp++;
            }
        }
        var newNumOfSteps = 0;
        if( step > 0 ) {
            newNumOfSteps = Math.floor(max/step);
        }
        var stepData = [];
        for(i=0;i<=newNumOfSteps;i++){
            stepData.push({
                "label":Math.round(i*step)+"\u20ac",
                "val":Math.round(i*step),
                "left":Math.round((i*step)/max*w)+"px"
            });
        }
        var lastStep = 0.0;
        if( stepData.length != 0 ) {
            lastStep = stepData[stepData.length-1].val;
        }
        var gridW = 0.0;
        if( newNumOfSteps !== null
            && ! isNaN(newNumOfSteps)
            && newNumOfSteps > 0
            && minorGridLineCount !== null
            && ! isNaN(minorGridLineCount)
            && minorGridLineCount > 0
        ) {
            gridW = lastStep / (newNumOfSteps*minorGridLineCount);
        }
        var gridWPx = 0.0;
        if( max !== null
            && ! isNaN(max)
            && max > 0
            && w !== null
            && ! isNaN(w)
            && w > 0
        ) {
          gridWPx = gridW/max*w;
        }
        var lastSteps = 0.0;
        if( ! isNaN(gridW) && gridW > 0 ) {
            lastSteps = Math.floor((max-lastStep)/gridW);
        }
        return {"gridWidth":gridW,"gridWidthPx":gridWPx,"gridLineCount":(minorGridLineCount*newNumOfSteps+lastSteps),"step":step,"numOfSteps":newNumOfSteps,"stepData":stepData};
    },
    animate:function(w){
        setTimeout(function(){
            $("#AirbagCurBar").animate({
                width:w+"px",
                opacity:1
            }, 280,function(){});
        }, 500);
    },
    update:function(p){
        p=jQuery.parseJSON(p);
        var cur=parseInt($("#CurrentUsageValue").html());
        var target=parseInt(p.KostenAirbagMonthMax);
        var prog=parseInt($("#ProjectedUsageValue").html());
        $("#AirbagTargetVal").html(target);
        Airbag.load(cur,target,prog,4);
        var m="";
        var diff=0;
        var pct=0;

        if(target<prog){
            diff=Math.abs(prog-target);
            pct=0;
            if(target>0){pct=Math.round(diff/target*100);}
            var verb=(prog>target)?I18n.JS_COST_AIRBAG_FORECAST_MESSAGE_NOT_ON_SCHEDULE_ABOVE:I18n.JS_COST_AIRBAG_FORECAST_MESSAGE_NOT_ON_SCHEDULE_BELOW;
            m= Util.sprintf(I18n.JS_COST_AIRBAG_FORECAST_MESSAGE_NOT_ON_SCHEDULE, verb, '<strong>', pct, diff, I18n.JS_CURRENCY, '</strong>');
        } else if(target>=prog){
            m= I18n.JS_COST_AIRBAG_FORECAST_MESSAGE_ON_SCHEDULE;
        }
        $("#AirbagMessage").html(m);
    },
    d:0
};

var Control = {
    minHeat:10,
    maxHeat:30,
    INDEFINABLE_SELECTOR:'Indefinable',
    INDEFINITE_CLASS_NAME:'Indefinite',
    lockSlider:null,
    lockControl:null,
    wasChanged:{},
    setValue:function( containerId, value, state, dim ) {
        var sel = '#' + containerId;
        if($(sel).length > 0) {
            // prevent self-affected updates through ajax
            Control.lockControl = containerId;

            // handle switches
            $( '#' + containerId + ' input:checkbox' ).attr( 'checked', state ).trigger( 'change' );

            // handle sliders
            if( containerId != Control.lockSlider ) {
                // dimmer
                $( "#Slider_" + containerId ).slider( 'option', 'value', value );
                $("#SliderVal_"+containerId).html( '' + value + dim );

                // thermostat
                $( "#Heat_" + containerId ).slider( 'option', 'value', value );
                Thermostat.setValue( '#HeatVal_' + containerId, value, dim );

                // blinds
                $( "#Blinds_" + containerId ).slider( 'option', 'value', value );
                Blinds.setValue( '#BlindsVal_' + containerId, value, dim );
            }

            // unlock control
            Control.lockControl = null;
        }
    },
    registerOnOff:function(sel, tagWithId, deviceStateSettable){
        $(sel).iButton({});
        if(tagWithId) {
            $(sel).change(function(){
                var containerId=$(this).closest(tagWithId).attr('id');
                if(containerId){
                    Control.onOffToggle(this, containerId, deviceStateSettable);
                }
            });
        }
    },
    onOffToggle:function(checkbox, containerId, deviceStateSettable){
        var on=checkbox.checked;
        if(on){
            $("#"+containerId+" h1").removeClass("Off");
            $("#SliderVal_"+containerId).removeClass("Off");
            $("#ControlMessage_"+containerId).removeClass("Off");
            if($("#Slider_"+containerId)){
                $("#Slider_"+containerId).slider("enable");
            }
        }else{
            $("#"+containerId+" h1").addClass("Off");
            $("#SliderVal_"+containerId).addClass("Off");
            $("#ControlMessage_"+containerId).addClass("Off");
            if($("#Slider_"+containerId)){
                $("#Slider_"+containerId).slider("disable");
            }
        }
        if(deviceStateSettable) {
            // --- set new device state via AJAX request ---
            var foundDevice = containerId.search( /Device_/ );
            var foundGroup = containerId.search( /Group_/ );
            if( foundDevice != -1 || foundGroup != -1 ) {
                var indexBeforeId = containerId.lastIndexOf( "_" );
                var id = 0;
                if( indexBeforeId != -1 ) {
                    var idString = containerId.substr(
                        indexBeforeId + 1,
                        containerId.length - indexBeforeId - 1
                    );
                    if( containerId != Control.lockControl ) {
                        Control.wasChanged[ containerId ] = new Date().getTime() + 60 * 1000;
                        Control.setIndefinite(containerId);
                        id = parseInt( idString );
                        if( foundDevice != -1 ) { // device toggle
                            $.ajax({
                                url: webroot + '/ajax/set-device-state',
                                data: {'deviceId' : id, 'state' : on},
                                dataType: 'json',
                                cache: false,
                                success: function( json ){
                                    Control.wasChanged[ containerId ] = new Date().getTime();
                                    Util.evalResponse(json);
                                },
                                failure: function( json ){
                                    Control.wasChanged[ containerId ] = new Date().getTime();
                                    Util.evalResponse(json);
                                }
                            });
                        }
                        else { // group toggle
                            $.ajax({
                                url: webroot + '/ajax/set-group-state',
                                data: {'groupId' : id, 'state' : on},
                                dataType: 'json',
                                cache: false,
                                success: function( json ){
                                    Util.evalResponse(json);
                                    Control.removeIndefinite(containerId);
                                },
                                failure: function( json ){
                                    Util.evalResponse(json);
                                    Control.removeIndefinite(containerId);
                                }
                            });

                        }
                    } // lockControl
                }
            }
        }
    },
    _initSlider:function(containerId, sliderVal, on,  min, max){
        $("#Slider_"+containerId).slider({
            range:      "min",
            min:        parseInt(min),
            max:        parseInt(max),
            value:      parseInt(sliderVal),
            disabled:   true,
            slide:function(event, ui) {
                var dim = $("#Slider_"+containerId).attr("dim");
                if(dim==undefined){
                    dim='';
                }
                $("#SliderVal_"+containerId).html(''+ui.value+dim);
            },
            start:function(event, ui) {
                // prevent UI updates while sliding
                Control.lockSlider = containerId;
            },
            stop:function(event, ui ) {
                Control.lockSlider = null;
            },
            change:function(event, ui) {
                var dim = $("#Slider_"+containerId).attr("dim");
                if(dim==undefined){
                    dim='';
                }
                $('#SliderVal_'+containerId).html(''+ui.value+dim);
                $('#Slider_'+containerId+' input:hidden').attr('value', ui.value);
            }
        });
        if(on){
            $("#Slider_"+containerId).slider("enable");
        }else{
            $("#Slider_"+containerId).slider("disable");
        }
    },
    createSlider:function(containerId, sliderVal, on, dim, min, max, deviceStateSettable){
        if(!dim) {
            dim="%";
        }
        Control._initSlider(containerId, sliderVal, on, min, max);
        $("#Slider_"+containerId).slider({stop:function(event, ui) {
            if(deviceStateSettable) {
                var deviceId=containerId.replace("Device_","");
                if( containerId != Control.lockControl ) {
                    Control.setIndefinite(containerId);
                    $.ajax({
                        url: webroot+"/ajax/set-device-state",
                        data: {"deviceId":deviceId,"value":ui.value},
                        cache: false,
                        success: function( json ){
                            Util.evalResponse(json);
                        },
                        failure: function( json ){
                            Util.evalResponse(json);
                        }
                    });
                } // lockControl
            }
        }});
    },
    createAutomationSlider:function(containerId, sliderVal, on, dim, min, max){
        if(dim==undefined){dim="%"}
        Control._initSlider(containerId, sliderVal, on, min, max);
        $("#Slider_"+containerId).slider({change:function(event, ui) {
            $('#'+containerId).val(ui.value);
        }});
    },
    heatToggle:function(status){
        var on=status==undefined?$('#HeatContainer input').attr("checked"):status;
        $('#HeatContainer input').attr("checked", on);
        $('#HeatContainer input').trigger("change");
        var add="";
        var remove="Off";
        if(!on){add="Off";remove="On";}
        $("#HeatContainer .HeatVal").removeClass(remove);
        $("#HeatContainer .HeatVal").addClass(add);
    },
    heatDown:function(){
        var v=Number($(".HeatValRaw").html());
        v=(v<=this.minHeat)?v:v-1;
        $(".HeatValRaw").html(v);
    },
    heatUp:function(){
        var v=Number($(".HeatValRaw").html());
        v=(v>=this.maxHeat)?v:v+1;
        $(".HeatValRaw").html(v);
    },
    setIndefinite:function(containerId){
        $('#'+containerId+' .'+Control.INDEFINABLE_SELECTOR).animate({
            opacity:.3
        },{
            duration:'fast'
        });
    },
    removeIndefinite:function(containerId){
        $('#'+containerId+' .'+Control.INDEFINABLE_SELECTOR).animate({
            opacity:1
        });
    },
    d:0
};

var Thermostat = {
    minHeat:4,
    maxHeat:28,
    setValue:function( containerId, value, dim ) {
        $( containerId ).html( value + dim );
    },
    createSlider:function(containerId, sliderVal, on, dim, min, max, deviceStateSettable ){
        if(dim == undefined){
            dim = '°C';
        }
        var slider = $("#Heat_"+containerId).slider({
            range:      "min",
            min:        min,
            max:        max,
            value:      sliderVal,
            slide:function(event, ui) {
                Thermostat.setValue( '#HeatVal_' + containerId, ui.value, dim );
            },
            start:function(event, ui) {
                // prevent UI updates while sliding
                Control.lockSlider = containerId;
            },
            stop:function(event, ui ) {
                Control.lockSlider = null;
            },
            change:function(event, ui) {
                $('#Heat_'+containerId+' input:hidden').attr('value', ui.value);
                if ( deviceStateSettable ) {
                    var deviceId=containerId.replace("Device_","");
                    if( containerId != Control.lockControl ) {
                        Control.wasChanged[ containerId ] = new Date().getTime() + 60 * 1000;
                        Control.setIndefinite( containerId );
                        $.ajax({
                            url: webroot+"/ajax/set-device-state",
                            data: {"deviceId":deviceId,"value":ui.value},
                            cache: false,
                            success: function( json ){
                                Control.wasChanged[ containerId ] = new Date().getTime();
                                Util.evalResponse(json);
                            },
                            failure: function( json ){
                                Control.wasChanged[ containerId ] = new Date().getTime();
                                Util.evalResponse(json);
                            }
                        });
                    } // lockControl
                } // settable
            }
        });
        $( '#' + containerId + " .ThermostatUp").mousedown(function(){
            var slider = $("#Heat_"+containerId);
            var value = $(slider).slider( "value" );
            if( value < max ) value++;
            $(slider).slider( "value" ,  value );
            Thermostat.setValue( '#HeatVal_' + containerId, value, dim );
        });
        $( '#' + containerId + " .ThermostatDown").mousedown(function(){
            var slider = $("#Heat_"+containerId);
            var value = $(slider).slider( "value" );
            if( value > min ) value--;
            $(slider).slider( "value" , value );
            Thermostat.setValue( '#HeatVal_' + containerId, value, dim );
        });
    }
}


var Blinds = {
    BACKGROUND_POSITION_X: -465,
    BACKGROUND_POSITION_Y_OPEN: -457,
    BACKGROUND_RANGE: 37,
    setValue:function( containerId, value, dim ) {
        $( containerId ).html( value + dim );
    },
    animate:function(containerId, val){
        var bgPosition = Blinds.BACKGROUND_POSITION_Y_OPEN + val/100*Blinds.BACKGROUND_RANGE;
        $('#'+containerId+' .BlindsControlAnimation').css({
            'background-position':Blinds.BACKGROUND_POSITION_X+'px '+bgPosition+'px'
        });
    },
    createSlider:function(containerId, sliderVal, on, dim, min, max, deviceStateSettable ){
        Blinds.animate(containerId, sliderVal);
        if(dim == undefined){
            dim = '%';
        }
        var slider = $("#Blinds_"+containerId).slider({
            range:      "min",
            min:        min,
            max:        max,
            value:      sliderVal,
            slide:function(event, ui) {
                Thermostat.setValue( '#BlindsVal_' + containerId, ui.value, dim );
                Blinds.animate(containerId, ui.value);
            },
            start:function(event, ui) {
                // prevent UI updates while sliding
                Control.lockSlider = containerId;
            },
            stop:function(event, ui ) {
                Control.lockSlider = null;
            },
            change:function(event, ui) {
                Blinds.animate(containerId, ui.value);
                $('#Blinds_'+containerId+' input:hidden').attr('value', ui.value);
                if( deviceStateSettable ) {
                    var deviceId=containerId.replace("Device_","");
                    if( containerId != Control.lockControl ) {
                        Control.wasChanged[ containerId ] = new Date().getTime() + 60 * 1000;
                        Control.setIndefinite( containerId );
                        $.ajax({
                            url: webroot+"/ajax/set-device-state",
                            data: {"deviceId":deviceId,"value":ui.value},
                            cache: false,
                            success: function( json ){
                                Control.wasChanged[ containerId ] = new Date().getTime();
                                Util.evalResponse(json);
                            },
                            failure: function( json ){
                                Control.wasChanged[ containerId ] = new Date().getTime();
                                Util.evalResponse(json);
                            }
                        });
                    } // lockControl
                }
            }
        });
        $( '#' + containerId + " .BlindsUp").mousedown(function(){
            var slider = $("#Blinds_"+containerId);
            var value = 0;
            $(slider).slider( "value" ,  value );
            Blinds.setValue( '#BlindsVal_' + containerId, value, dim );
        });
        $( '#' + containerId + " .BlindsDown").mousedown(function(){
            var slider = $("#Blinds_"+containerId);
            var value = 100;
            $(slider).slider( "value" , value );
            Blinds.setValue( '#BlindsVal_' + containerId, value, dim );
        });
    }
}

var Schedule = {
    onOffToggle:function(radio, containerId){
        var sId=containerId.replace('Schedule_','');
        var scheduleOperation = 'scheduleDisable';
        if( radio.checked ) {
            scheduleOperation= 'scheduleEnable';
        }
        $.ajax({
            url:webroot+'/ajax/schedule',
            cache:false,
            data:{'scheduleId':sId,'scheduleOperation':scheduleOperation}
        });
    },
    remove:function(p){
        Util.showLoader();
        $.ajax({
            url:webroot+'/ajax/schedule',
            cache:false,
            data:{'scheduleId':p.scheduleId,'scheduleOperation':'scheduleDelete'},
            success:function(json){
                Util.hideLoader();
                try{
                    if(json.code==0){
                        if(p.hideOnDelete){
                            Schedule.hideFromList(p.scheduleId);
                        }
                    }
                }catch(e){
                }
            }
        });
    },
    hideFromList:function(scheduleId){
        var el=$('#Schedule_'+scheduleId);
        setTimeout(function(){
            $(el).animate({opacity:0},{
                duration:200,
                complete:function(){
                    $('#Schedule_'+scheduleId+' .HideOnRemove').remove();
                    $('#Schedule_'+scheduleId+' td').animate({height:0},{
                        duration:200,
                        complete:function(){
                            $(el).remove();
                        }
                    });
                }
            });
        }, 400);
    },
    registerDelete:function(selector){
        $(selector).click(function(){
            var sId=$(this).closest('tr').attr('id').replace('Schedule_','');
            var ruleName = $('#Schedule_'+sId+' .ElementName').html();
            var deleteConfirmed = confirm( Util.sprintf( I18n.JS_CONFIRM_RULE_DELETION, ruleName ) );
            if(deleteConfirmed){
                Schedule.remove({scheduleId:sId,hideOnDelete:true});
            }
        });
    },
    d:0
};

var Automation = {
    updateList:function(source){
        $("#AutomationScrollable .item").each(function(){$(this).removeClass("Selected");});
        $(source).addClass("Selected");
    },
    updateHomeControlList:function(html){
        $("#turnedOnList").html(html);
    },
    animateControlPanels:function(programId){
        if(programId==1){
            $("#Device_1 input").attr("checked",true).trigger("change");
            $("#Device_2 input").attr("checked",true).trigger("change");
            $("#Device_3 input").attr("checked",true).trigger("change");
            $("#Slider_Device_3").slider("value", 100);
            $("#Device_4 input").attr("checked",true).trigger("change");
            $("#Device_5 input").attr("checked",true).trigger("change");
            $("#Slider_Device_5").slider("value", 100);
            Automation.animateNumber({id:"HeatValRaw",newVal:20});
            Control.heatToggle(true);
        }else if(programId==2){
            $("#Device_1 input").attr("checked",false).trigger("change");
            $("#Device_2 input").attr("checked",false).trigger("change");
            $("#Device_3 input").attr("checked",false).trigger("change");
            $("#Slider_Device_3").slider("value", 0);
            $("#Device_4 input").attr("checked",false).trigger("change");
            $("#Device_5 input").attr("checked",false).trigger("change");
            $("#Slider_Device_5").slider("value", 0);
            Automation.animateNumber({id:"HeatValRaw",newVal:18});
            Control.heatToggle(true);
        }else if(programId==3){
            $("#Device_1 input").attr("checked",false).trigger("change");
            $("#Device_2 input").attr("checked",true).trigger("change");
            $("#Device_3 input").attr("checked",true).trigger("change");
            $("#Slider_Device_3").slider("value", 50);
            $("#Device_4 input").attr("checked",false).trigger("change");
            $("#Device_5 input").attr("checked",true).trigger("change");
            $("#Slider_Device_5").slider("value", 20);
            Automation.animateNumber({id:"HeatValRaw",newVal:16});
            Control.heatToggle(true);
        }else if(programId==4){
            $("#Device_1 input").attr("checked",false).trigger("change");
            $("#Device_2 input").attr("checked",false).trigger("change");
            $("#Device_3 input").attr("checked",false).trigger("change");
            $("#Slider_Device_3").slider("value", 0);
            $("#Device_4 input").attr("checked",true).trigger("change");
            $("#Device_5 input").attr("checked",false).trigger("change");
            $("#Slider_Device_5").slider("value", 0);
            Automation.animateNumber({id:"HeatValRaw",newVal:10});
            Control.heatToggle(false);
        }
        $("#StandBy input").trigger("change");
        $("#Schlafzimmer input").trigger("change");
        $("#Wohnzimmer input").trigger("change");
        $("#LichtGesamt input").trigger("change");
        $("#Jalousien input").trigger("change");
    },
    animateNumber:function(p){
        var duration=p.duration?p.duration:400;
        var val=p.curVal?p.curVal:parseInt($("#"+p.id).html());
        if(val!=p.newVal){
            var d=duration/Math.abs(val-p.newVal);
            var i=setInterval(function(){
                if(val<p.newVal){val++;}else{val--;}
                $("#"+p.id).html(val);
                if(val==p.newVal){clearInterval(i);}
            }, d);
        }
    },
    animateSlider:function(p){
        dim="%";
        if(p.dim){dim=p.dim;}
        $("#Slider_"+p.id+" .ui-slider-handle").animate({
                left:p.val+dim
            },{
                step: function(v){$("#SliderVal_"+p.id).html(Math.round(v)+dim);}
            }
        );
    },
    onOffToggle:function(radio, containerId){
        var on=radio.checked;
        if(on){
            $(".AutomationElement h1").each(function(){$(this).addClass("Off")});
            $("#"+containerId+" h1").removeClass("Off");
        }else{
            $("#"+containerId+" h1").addClass("Off");
        }
    },

    d:0
};

Branch = {
    data:null,
    sum:null,
    compare:null,
    sortKey:"cost",
    prevSortKey:"",
    sortDirAsc:"asc",
    sortDirDesc:"desc",
    sortIconCssClass:"SortIcon",
    sortDirAscCssClass:"SortIconAsc",
    sortDirDescCssClass:"SortIconDesc",
    sortDir:"asc",
    rankKey:"cost",
    load:function(p){
        if(p==undefined){
            p={};
        }
        var params = {
            "category":Graph.postParams.category,
            "period":Graph.postParams.period,
            "startTime":Graph.postParams.startTime
        };
        $.ajax({
            url: webroot+"/ajax/branch-data",
            data:params,
            dataType:"json",
            cache: false,
            success: function(json){
                Branch.data=json.branchData;
                Branch.sum=json.sum;
                Branch.compare=json.compare;
                if(p.sort) {
                    var thisKeepSortDir=p.keepSortDir!=undefined?p.keepSortDir:false;
                    Branch.sortData({keepSortDir:thisKeepSortDir});
                    Branch.assignRanking(true);
                    Branch.sortTable();
                }
                Branch.updateTable();
                Branch.updateSum();
                Branch.updateCompare();
                Branch.updateBars();
            }
        });
    },
    setSortKey:function(v){
        Branch.prevSortKey=Branch.sortKey;
        Branch.sortKey=v;
    },
    getSortKey:function(){
        return Branch.sortKey;
    },
    setRankKey:function(v){
        Branch.rankKey=v;
    },
    setSortDir:function(dir){
        Branch.sortDir=dir;
    },
    toggleSortDir:function(){
        Branch.sortDir=Branch.sortDir==Branch.sortDirDesc?Branch.sortDirAsc:Branch.sortDirDesc;
    },
    isNewSortKey:function(){
        if(Branch.sortKey==Branch.prevSortKey){
            return true;
        }else{
            return false;
        }
    },
    sortData:function(keepSortDir){
        if(keepSortDir==undefined || !keepSortDir) {
            if(Branch.isNewSortKey()){
                Branch.toggleSortDir()
            }else{
                Branch.setSortDir(Branch.sortDirAsc);
            }
        }
        Branch.data.sort(function (a,b) {
            var v1=a[Branch.sortKey];
            var v2=b[Branch.sortKey];
            var r1=1;
            var r2=-1;
            if(Branch.sortDir==Branch.sortDirDesc){
                r1=-1;
                r2=1;
            }
            if(v1>v2){return r1;}
            else if(v1<v2){return r2;}
            else{return 0;}
        });
    },
    assignRanking:function(doUpdate){
        var valToRank = [];
        $.each(Branch.data, function(k,v){
            valToRank.push({
                id:v.id,
                value:v[Branch.rankKey]
            });
        });
        valToRank.sort(function(a,b){
            return a.value>b.value
        });
        $.each(Branch.data, function(k,v){
            $.each(valToRank, function(k2,v2){
                if(v.id==v2.id){
                    v.rank=k2+1;
                    return;
                }
            });
            if(doUpdate){
                $("#Branch_"+v.id+"_rank").html(v.rank);
            }
        });
    },
    sortTable:function(){
        $.each(Branch.data, function(k,v){
            if(v.id!=0){
                $("#EfficiencyAnalyisTable tbody").append($("#Branch_"+v.id));
            }
        });
    },
    setSortIcon:function(id){
        $(".SortIcon").each(function(){
            $(this).removeClass(Branch.sortDirAscCssClass);
            $(this).removeClass(Branch.sortDirDescCssClass);
        })
        var sortIconClass=Branch.sortDir==Branch.sortDirAsc?Branch.sortDirAscCssClass:Branch.sortDirDescCssClass;
        $("#"+id+" ."+Branch.sortIconCssClass).addClass(sortIconClass);
    },
    getActivated:function(){
        var r=[];
        $(".BranchCheckbox").each(function(){
            if($(this).attr("checked")){
                var id=$(this).attr("id").replace("BranchCheckbox_","");
                r.push(id);
            }
        });
        return r;
    },
    updateTable:function(){
        $.each(Branch.data, function(k,v){
            $('#Branch_'+v.id+'_displayColor').css('color', v.displayColor);
            $.each(v.table, function(k2,v2){
                var id = "#Branch_"+v.id+"_"+k2;
                $(id).html(v2);
            })
        });
    },
    updateSum:function(){
        if(Branch.sum) {
            $.each(Branch.sum, function(k,v){
                var id = "#Branch_0_"+k;
                $(id).html(v);
            });
        }
    },
    updateCompare:function(){
        if(Branch.compare) {
            $.each(Branch.compare, function(k,v){
                var id = "#Branch_4_"+k;
                $(id).html(v);
            });
        }
    },
    updateBars:function(){
        var key=["saving12MonthsPct"];
        if(Branch.compare) {
            key=["savingLastMonthPct"];
        }
        var max=[0];
        var thisData = Branch.data;
        thisData.push(Branch.sum);
        $.each(thisData, function(k,v){
            $.each(key, function(barKey,barName){
                var val=Math.abs(v[barName]);
                if(val>max[barKey]){
                    max[barKey]=val;
                }
            });
        });
        $.each(thisData, function(k,v){
            $.each(key, function(barKey,barName){
                var bar=$("#Branch_"+v.id+"_Bar_"+barName);
                var next=$("#Branch_"+v.id+"_Bar_"+barName+" div:first-child");
                next.removeClass("InnerBarPositive");
                next.removeClass("InnerBarNegative");
                var val=v[barName];
                var cssClass=val>=0?"InnerBarPositive":"InnerBarNegative";
                var w=Math.abs((val/max[barKey])*parseInt(bar.width()/2)*.95);
                var left=val>=0?bar.width()/2:bar.width()/2-w;
                next.addClass(cssClass);
                next.css("width",w+"%");
                next.css("left",left+"px");
                if(val<0){
                    var offset=(bar.width()-w)*-1;
                    next.css("backgroundPosition", offset+"px 0");
                }
            });
        });
    },
    isSubColumn:function(colName){
        var result = false;
        var map={
            "cost":["cost","costPerArea","costPerEmployee"],
            "consumption":["consumption","consumptionPerArea","consumptionPerEmployee"],
            "co2":["co2","co2PerArea","co2PerEmployee"],
            "saving":["savingLastMonthPct","saving3MonthsPct","saving12MonthsPct"]
        };
        if(map[colName]){
            $.each(map[colName], function(k,v){
                if(v==Branch.getSortKey()){
                    result = true;
                    return false;
                }
            })
        }
        return result;
    },
    registerCheckboxes:function(){
        $(".BranchCheckbox").change(function(event){
            Graph.load({"multipleId":Branch.getActivated()});
        });
    }
};

var Graph = {
    ready:false,
    flashReady:false,
    view:null,
    options:{
        "flashFile":"graph.swf",
        "flashConfigFile":"config.xml",
        "id":"Flash",
        "width":"680",
        "height":"300"
    },
    postParams:{
        "multiple":"false",
        "multipleId":[],
        "category":"",
        "type":"",
        "period":"year",
        "topic":"",
        "consumerId":"",
        "startTime":"",
        "startTime2":""
    },
    getFlashFile:function(){
        var r = '';
        if(
            typeof(Settings) != 'undefined'
            && typeof(Settings.theme) != 'undefined'
            && typeof(Settings.symlinkedTheme) != 'undefined'
        ) {
            if(Settings.symlinkedTheme) {
                r = Util.sprintf('%s/%s/%s', Settings.webroot, 'flash', Graph.options.flashFile);
            } else {
                r = Util.sprintf('%s/%s/%s/%s', Settings.webroot, 'shared', 'flash', Graph.options.flashFile);
            }
        }
        return r;
    },
    getFlashConfigFile:function(){
        var r = '';
        if(
            typeof(Settings) != 'undefined'
            && typeof(Settings.theme) != 'undefined'
            && typeof(Settings.symlinkedTheme) != 'undefined'
        ) {
            if(Settings.symlinkedTheme) {
                r = Util.sprintf('%s/%s/%s/%s', Settings.webroot, 'flash', Util.getLang(), Graph.options.flashConfigFile);
            } else {
                r = Util.sprintf('%s/%s/%s/%s/%s/%s', Settings.webroot, 'themes', Util.getTheme(), 'flash', Util.getLang(), Graph.options.flashConfigFile);
            }
        }
        return r;
    },
    init:function(p,opt){
            $.extend(this.postParams,p);
            $.extend(this.options,opt);
            this.embedFlash();
    },
    embedFlash:function(){
        var flashvars = {
            delay: 1000,
            maxtime: 20000,
            conf:Graph.getFlashConfigFile()
        };
        var params = {
            quality: "high",
            wmode: "opaque",
            bgcolor: "#ffffff",
            allowfullscreen: "true",
            allowscriptaccess: "always"
        };
        var attributes = {
            id: "graph",
            name: "graph"
        };
        swfobject.embedSWF(Graph.getFlashFile(), Graph.options.id, Graph.options.width, Graph.options.height, "9.0.0","expressInstall.swf", flashvars, params, attributes);
        Graph.load({});
    },
    setReady:function(){this.ready=true;},
    isReady:function(){return this.ready;},
    setFlashReady:function(){this.flashReady=true;},
    isFlashReady:function(){return this.flashReady;},
    load:function(opt){
        Util.showLoader();
        $.extend(this.postParams,opt);
        Graph.fadeViewVars();
        $.ajax({
            url: webroot+"/ajax/consumption-data",
            data:Graph.postParams,
            dataType:"json",
            cache: false,
            success: function(json){
                Util.evalResponse(json);
                var d=$.toJSON(json.data);
                if(Graph.postParams.multiple==true || Graph.postParams.multiple=="true"){
                    var activated=Branch.getActivated();
                    var theseParts=[];
                    var val=[];
                    $.each(json.data.graphs[0].parts, function(k,branch){
                        if($.inArray(""+branch.id, activated)>=0){
                            theseParts.push(branch);
                            $.merge(val, branch.rows[0].data);
                        }
                    });
                    val = jQuery.grep(val, function(n, i){
                        return (n!="n");
                    });
                    val.sort(function(a,b){return b-a});
                    json.data.graphs[0].topValue=val[0]*1.1;
                    json.data.graphs[0].parts=theseParts;
                    d=$.toJSON(json.data);
                }
                var myInt = setInterval(function(){
                    if(Graph.isFlashReady()){
                        clearInterval(myInt);
                        $("#graph")[0].setJson(d);
                    }
                },200);
                Graph.view = json.data.view;
                Graph.updateViewVars(json.data.view);
                Graph.showPeriodControl();
                if( typeof json.data.indicator != "undefined" ) {
                    Graph.updateIndicator(json.data.indicator);
                }
                Graph.removeOverlay('temp');
                Graph.removeOverlay('productivity');
                if(json.data.general.startTime2){Graph.postParams.startTime2=json.data.general.startTime2;}
                Util.hideLoader();
            },
            error: function(json) {
                Util.hideLoader();
            }
        });
    },
    print:function(){alert("printing...");},
    showPeriodControl:function(){
        if(this.postParams.topic=="periodCompare"){
            $("#GraphPeriodControl2").show();
            $("#graphPeriod").removeClass("graphPeriod");
            $("#graphPeriod").addClass("graphPeriod2");
        }else{
            $("#GraphPeriodControl2").hide();
            $("#graphPeriod").removeClass("graphPeriod2");
            $("#graphPeriod").addClass("graphPeriod");
        }
        $('.GraphPeriodControlLeft').removeClass('GraphPeriodControlLeftInactive');
        $('.GraphPeriodControlRight').removeClass('GraphPeriodControlRightInactive');
        if(!Graph.view.prevStartTime){
            $('#GraphPeriodControlLeft').addClass('GraphPeriodControlLeftInactive');
        }
        if(!Graph.view.prevStartTime2){
            $('#GraphPeriodControlLeft2').addClass('GraphPeriodControlLeftInactive');
        }
        if(!Graph.view.nextStartTime){
            $('#GraphPeriodControlRight').addClass('GraphPeriodControlRightInactive');
        }
        if(!Graph.view.nextStartTime2){
            $('#GraphPeriodControlRight2').addClass('GraphPeriodControlRightInactive');
        }
    },
    fadeViewVars:function(){
        $(".ViewVar").each(function(){$(this).addClass("faded");})
    },
    updateViewVars:function(json){
        $.each(json, function(k,v){
            if($("#"+k).length>0){
                $("#"+k).html(v);
                $("#"+k).removeClass("faded");
            }
        })
    },
    updateIndicator:function(json){
        if(this.postParams.category!="house") {
            $("#IndicatorValue").html(json.value);
            $("#IndicatorDimension").html(json.dimension);
            $("#TopicIcon").attr("class","");
            $("#TopicIcon").addClass("TopicIcon");
            $("#TopicIcon").addClass(json.iconClass);
            $("#IndicatorDesc").html(json.text1);
            $("#IndicatorCondition").html(json.text2);
        }
    },
    activateButton:function(id,source,type,area){
        area = (area!=undefined)?area.charAt(0).toUpperCase()+area.substr(1):"";
        var cssClass = "";
        var groupId = "";
        var domIdString = "";
        if(source=="type"){
            groupId = "GraphTypeButtons";
            cssClass = "Selected";
            domClassString = "#"+groupId+" li a";
            domIdString = "#"+id+" a";
            $(".GraphTopicButtons"+area).each(function(){$(this).hide()});
            $("#"+type+"Buttons"+area).effect("slide",{},200);
        }else if(source=="period"){
            groupId = "GraphPeriodButtons";
            cssClass = area+"ButtonSelected";
            domClassString = "#"+groupId+" ."+area+"Button";
            domIdString = "#"+id;
        }else if(source=="topic"){
            groupId = "GraphTopicButtons"+area;
            cssClass = "Selected";
            domClassString = "."+groupId+" li";
            domIdString = "#"+id;
        }
        $(domClassString).each(function(){
            if(source=="period"){
                $("#"+this.id+" .ButtonLeft").addClass("ElementIcon");
                $("#"+this.id+" .ButtonLeft").removeClass("ColoredElementIcon");
                $("#"+this.id+" .ButtonRight").addClass("ElementIcon");
                $("#"+this.id+" .ButtonRight").removeClass("ColoredElementIcon");
                $(this).removeClass(cssClass);
            }else if(source=="topic"){
                $(domClassString).removeClass(cssClass);
            }else{
                $(this).addClass("ElementIcon");
                $(this).removeClass("ColoredElementIcon");
                $(this).removeClass(cssClass);
            }
        })
        if(source=="period"){
            $(domIdString+" .ButtonLeft").removeClass("ElementIcon");
            $(domIdString+" .ButtonLeft").addClass("ColoredElementIcon");
            $(domIdString+" .ButtonRight").removeClass("ElementIcon");
            $(domIdString+" .ButtonRight").addClass("ColoredElementIcon");
            $(domIdString).addClass(cssClass);
        }else if(source=="topic"){
            $(domIdString).parent().addClass(cssClass);
        }else{
            $(domIdString).removeClass("ElementIcon");
            $(domIdString).addClass("ColoredElementIcon");
            $(domIdString).addClass(cssClass);
        }
    },
    changePeriod:function(dir){
        if(dir=="prev" && Graph.view.prevStartTime){
            Graph.postParams.startTime=Graph.view.prevStartTime;
            Graph.load();
        } else if(dir=="next" && Graph.view.nextStartTime){
            Graph.postParams.startTime=Graph.view.nextStartTime;
            Graph.load();
        } else if(dir=="prev2" && Graph.view.prevStartTime2){
            Graph.postParams.startTime2=Graph.view.prevStartTime2;
            Graph.load();
        } else if(dir=="next2" && Graph.view.nextStartTime2){
            Graph.postParams.startTime2=Graph.view.nextStartTime2;
            Graph.load();
        }
    },
    removeOverlay:function(type){
        if (type=='productivity') {
            $('#GraphCanvasOverlayWork').remove();
        } else if (type=='temp') {
            $('#GraphCanvasOverlayTemp').remove();
        }
    },
    createOverlay:function(cssClass){
        $('#GraphCanvas').append('<div id="GraphCanvasOverlay" class="'+cssClass+'"></div>');
    },
    showTemperature:function(show){
        Graph.removeOverlay('temp');
        if(show) {
            var cssClass = 'GraphCanvasOverlayTemp_'+Graph.postParams.period;
            $('#GraphCanvas').append('<div id="GraphCanvasOverlayTemp" class="'+cssClass+'"></div>');
        }
    },
    showProductivity:function(show){
        Graph.removeOverlay('productivity');
        if(show) {
            var cssClass = 'GraphCanvasOverlayWork_'+Graph.postParams.period;
            $('#GraphCanvas').append('<div id="GraphCanvasOverlayWork" class="'+cssClass+'"></div>');
        }
    },
    registerPeriodButtons:function(type, area){
        $("#year_button").click(function(){
            if(!$(this).hasClass('ButtonInactive')) {
                Graph.load({"period":"year", "startTime":null, "startTime2":null});
                Graph.activateButton($(this).attr("id"),"period",type,area);
                if(typeof loadTrendPartialPeriod === 'function') {
                    loadTrendPartialPeriod("year");
                }
            }
        });
        $("#month_button").click(function(){
            if(!$(this).hasClass('ButtonInactive')) {
                Graph.load({"period":"month", "startTime":null, "startTime2":null});
                Graph.activateButton($(this).attr("id"),"period",type,area);
                if(typeof loadTrendPartialPeriod === 'function') {
                    loadTrendPartialPeriod("month");
                }
            }
        });
        $("#week_button").click(function(){
            if(!$(this).hasClass('ButtonInactive')) {
                Graph.load({"period":"week", "startTime":null, "startTime2":null});
                Graph.activateButton($(this).attr("id"),"period",type,area);
                if(typeof loadTrendPartialPeriod === 'function') {
                    loadTrendPartialPeriod("week");
                }
            }
        });
        $("#day_button").click(function(){
            if(!$(this).hasClass('ButtonInactive')) {
                Graph.load({"period":"day", "startTime":null, "startTime2":null});
                Graph.activateButton($(this).attr("id"),"period",type,area);
                if(typeof loadTrendPartialPeriod === 'function') {
                    loadTrendPartialPeriod("day");
                }
            }
        });
    },
    d:0
};

var RateComparison = {
    id:null,
    myRate:{},
    availableRate:[],
    rateIndex:null,
    label:{
        p:(I18n)?I18n.JS_RATE_COMPARISON_SAVINGS:null,
        n:(I18n)?I18n.JS_RATE_COMPARISON_EXTRA_COSTS:null
    },
    getConsumption:function(){
        var r=null;
        if($("#CustomConsumptionOption").attr("checked")){
            r=parseInt($("#CustomConsumption").val());
            //if(r<0){
            //    r=0;
            //    $("#CustomConsumption").val(r);
            //}
        }else{
            r=parseInt($("#Consumption").html());
        }
        return r;
    },
    getCost:function(){
        return this.cost;
    },
    setMyRate:function(r){
        this.myRate=r;
    },
    setAvailableRate:function(r){
        this.availableRate=r;
    },
    setSelected:function(id){
        $("#AvailableRates tr").each(function(){$(this).removeClass("Selected")});
        $("#RateRow_"+id).addClass("Selected");
    },
    update:function(id){
        if(!id){
            id=this.id;
        }else{
            this.id=id;
        }
        this.setSelected(id);

        $.each(this.availableRate, function(k,v){
            if(v.id==id){RateComparison.rateIndex=k;return;}
        });
        var costDiff = this.calcCostDiff();
        this.updateOtherRate();
        this.updateCostDiff(costDiff);

        var currentCost=this.calcRateCost(this.myRate);
        var cost = this.calcRateCost(this.availableRate[this.rateIndex]);
        var costF = $().numberFormat(cost);
        costDiff = this.calcCostDiff(currentCost, cost);
        var co2Diff = this.calcCO2Diff();
        this.updateCurrentCost(currentCost);
        this.updateOtherRate(costF);
        this.updateCostDiff(costDiff);
        this.updateCO2Diff(co2Diff);
    },
    updateCurrentCost:function(cost){
        var costF=$().numberFormat(cost);
        $("#MyRateCostValue").html(costF);
    },
    updateOtherRate:function(cost){
        var o=this.availableRate[this.rateIndex];
        var basePriceF=$().numberFormat(o.basePrice);
        var co2RateF=$().numberFormat(o.co2Rate);
        var unitPrice=this.getUnitPrice();
        $("#OtherRateCostValue").html(cost);
        $("#OtherRateName").html(o.name);
        $("#OtherRateBasePrice").html(basePriceF+" "+o.basePriceUnit);
        $("#OtherRateUnitPrice").html(unitPrice);
        $("#OtherRateCO2Rate").html(co2RateF+" "+o.co2RateUnit);
        $("#RateComparisonOtherName").html(o.name)
    },
    getUnitPrice:function(){
        var s="";
        var temp=[];
        $.each(this.availableRate[this.rateIndex].rate, function(k,v){
            temp.push(v.label+": "+$().numberFormat(v.price*100,{numberOfDecimals:0}));
        });
        s=temp.join(", ");
        s+=" "+this.availableRate[this.rateIndex].unit;
        return s;
    },
    updateCostDiff:function(costDiff){
        var costDiffF = $().numberFormat(Math.abs(costDiff));
        var label=this.label.p;
        var remove="Negative";
        var add="Positive";
        if(costDiff<0){
            label=this.label.n;
            remove="Positive";
            add="Negative";
        }
        $("#RateComparisonTitle").html(label);
        $("#RateComparisonResult").addClass(add);
        $("#RateComparisonResult").removeClass(remove);
        $("#RateComparisonValue").html(costDiffF);
    },
    updateCO2Diff:function(diff){
        var d = $().numberFormat(diff, {numberOfDecimals:0});
        var remove="Positive";
        var add="Negative";
        if(diff<0){
            remove="Negative";
            add="Positive";
        }else if(diff>0){
            d="+"+d;
        }
        $("#RateComparisonCO2Result").addClass(add);
        $("#RateComparisonCO2Result").removeClass(remove);
        $("#RateComparisonCO2Value").html(d);
    },
    calcRateCost:function(ref){
        var consumption=this.getConsumption();
        var r=0;
        if(!isNaN(consumption)){
            $.each(ref.rate, function(k,v){
                r+=v.share*v.price*consumption;
            });
            r+=ref.basePrice;
        }
        return r;
    },
    calcCostDiff:function(currentCost, cost){
        var r=currentCost-cost;
        if(r<.01 && r>0){r=0;}
        return r;
    },
    calcCO2Diff:function(){
        var r=0;
        var consumption=this.getConsumption();
        if(!isNaN(consumption)){
            var currentCO2=this.myRate.co2Rate*consumption;
            var thisCO2=this.availableRate[this.rateIndex].co2Rate*consumption;
            r=thisCO2-currentCO2;
        }
        return r;
    },
    selectRandom:function(){
        var i=$.randomBetween(0,this.availableRate.length-1);
        this.update(this.availableRate[i].id);
    },
    d:0
};

var UpdateDevices = {
    SCOPE_DASHBOARD: 'dashboard',
    SCOPE_USER: 'user',
    scope: 'user', // not possible to use constant
    addStarting: false,
    removeStarting: false,
    timeoutId: undefined,
    initAll:function( scope, timeout ) {
        if( undefined != UpdateDevices.timeoutId ) {
            clearTimeout( UpdateDevices.timeoutId );
        }
        UpdateDevices.timeoutId = setTimeout( UpdateDevices.updateAll, typeof timeout === 'undefined' ? 2000 : timeout );
        if( undefined != scope ) {
            UpdateDevices.scope = scope;
        }
    },
    lastUpdated: 0,
    deviceCount: null,
    lockToken: false,
    updateAll:function() {
        if( ! UpdateDevices.lockToken ) {
            clearTimeout( UpdateDevices.timeoutId );
            UpdateDevices.timeoutId = undefined;

            UpdateDevices.lockToken = true;
            // get current time before requests starts
            var updateTime = new Date().getTime();
            $.ajax({
                type:"get",
                url: webroot+"/ajax/get-device-state",
                data: {
                    'deviceGroup' : UpdateDevices.scope,
                    'lastUpdated' : UpdateDevices.lastUpdated
                },
                dataType: "json",

                cache: false,
                success: function(json){
                    if( json.code == 113 ) {
                        // force reload for session timout
                        location.href=webroot;
                    }
                    else if( json.code == 0 ) {
                        if( typeof Demo.status !== 'undefined' ) {
                            if( 'running' == json.data.demo ) {
                                $("#Progress").progressbar({value: json.data.timeout});
                            }
                            else {
                                $("#Progress").progressbar( 'disable' );
                            }

                            if( Demo.status != json.data.demo ) {
                                Demo.status = json.data.demo;
                                if( 'pending' == json.data.demo ) {
                                    location.href=webroot;
                                }
                                else if( 'running' == json.data.demo ) {
                                    $('#DemoPending').hide();
                                    $('#DemoRunning').show();
                                }
                            }
                        }

                        if( json.data != null ) {
                            if( AjaxConst.CONTROLLERSTATE_OFFLINE == json.data.scanStatus ) {
                                $('#GatewayStatusOffline').show();
                                $('#GatewayStatusDisabled').hide();
                                $('#DeviceAdmin').hide();
                            }
                            else if( AjaxConst.CONTROLLERSTATE_DISABLED == json.data.scanStatus ) {
                                $('#GatewayStatusOffline').hide();
                                $('#GatewayStatusDisabled').show();
                                $('#DeviceAdmin').hide();
                            }
                            else {
                                if( DeviceAdminConst.STATE_IDLE != json.data.deviceAdminStatus ) {
                                    if( json.data.deviceAdminFinal ) {
                                        $('#DeviceScanLoader .InlineLoader').hide();
                                        $('#mrtOK').show();
                                    }
                                    
                                    $('#DeviceScanStatus').html( json.data.deviceAdminMessage );
                                        
                                    if( DeviceAdminConst.STATE_REMOVE_RUNNING == json.data.deviceAdminStatus ) {
                                        $('#DeviceScanMessage').hide();
                                        $('#DeviceRemoveImage').show();
                                        $('#DeviceRemoveInfo').show();
                                        $('#DeviceScanMessageWrap').slideDown(400);
                                        }
                                    else {
                                        $('#DeviceRemoveImage').hide();
                                        $('#DeviceRemoveInfo').hide();
                                        if( '' == json.data.deviceAdminInfo ) {
                                            $('#DeviceScanMessageWrap').slideUp(400);
                                            $('#DeviceScanMessage').hide();
                                        }
                                        else {
                                            $('#DeviceScanMessage').html( json.data.deviceAdminInfo );
                                            $('#DeviceScanMessage').show();
                                            $('#DeviceScanMessageWrap').slideDown(400);
                                        }
                                    }
                                }

                                $('.GatewayStatus').hide();
                                if( 0 == json.data.scanStatus ) {
                                    $('#DeviceAdmin').show();
                                    $('#DeviceScanRunning').hide();
                                    $('#DeviceRemoveRunning').hide();
                                    //if( ! UpdateDevices.removeStarting && ! UpdateDevices.addStarting ) {
                                    //    Util.closeMrT();
                                    //}
                                }
                                else {
                                    $('#DeviceAdmin').hide();
                                    if( AjaxConst.CONTROLLERSTATE_ADD == json.data.scanStatus ) {
                                        UpdateDevices.addStarting = false;
                                        $('#DeviceScanRunning').show();
                                        $('#DeviceRemoveRunning').hide();
                                    }
                                    else if( AjaxConst.CONTROLLERSTATE_REMOVE == json.data.scanStatus ) {
                                        UpdateDevices.removeStarting = false;
                                        $('#DeviceScanRunning').hide();
                                        $('#DeviceRemoveRunning').show();
                                    }
                                }
                            }


                            if( null != UpdateDevices.deviceCount
                             && UpdateDevices.deviceCount != json.data.deviceCount )
                            {
                                // refresh device table (only works for device page, not on dashboard)
                                if( UpdateDevices.SCOPE_USER == UpdateDevices.scope ) {
                                    Util.showLoader();
                                    $.ajax({
                                        url:webroot+'/control/geraete',
                                        cache:false,
                                        dataType:'html',
                                        success:function(r){
                                            $('#DeviceTable').fadeOut('slow',function(){
                                                $('#DeviceTableWrap').html(r);
                                                Device.controlDeviceOnload({'deviceIdParamName':'deviceId'});
                                                Util.hideLoader();
                                            });
                                        }
                                    });
                                }
                            }
                            UpdateDevices.deviceCount = json.data.deviceCount;

                            UpdateDevices.lastUpdated = json.data.lastUpdated;
                            for( var deviceId in json.data.deviceData ) {
                                var device = json.data.deviceData[ deviceId ];
                                if( device.deviceTypeId == 4 ) { // door sensor
                                    var el = $( '#SortableDevice_' + deviceId + ' .State' );
                                    if( device.sensorState == true || device.sensorState == false ) {
                                        if( device.sensorState == true ) {
                                            $(el).find(".ElementIcon").removeClass( 'sensorClosedIcon' );
                                            $(el).find(".ElementIcon").addClass( 'sensorOpenIcon' );
                                            $(el).find(".OneByTwoSensorMessage").html( I18n.JS_DEVICE_DOORSENSOR_OPEN );
                                        }
                                        else {
                                            $(el).find(".ElementIcon").removeClass( 'sensorOpenIcon' );
                                            $(el).find(".ElementIcon").addClass( 'sensorClosedIcon' );
                                            $(el).find(".OneByTwoSensorMessage").html( I18n.JS_DEVICE_DOORSENSOR_CLOSED );
                                        }
                                    }
                                    else {
                                        // don't change text on communication dropouts
                                    }
                                    if( device.sensorLastChanged ) {
                                        $('#SortableDevice_' + deviceId + ' .Log' ).find('.OneByTwoSensorMessage' ).html(
                                            Util.formatTimestamp( device.sensorLastChanged * 1000  )
                                        );
                                    }

                                }
                                else if( device.deviceTypeId   == 9
                                      || device.deviceTypeId   == 12
                                ) {// motion detector
                                    var el = $( '#SortableDevice_' + deviceId + ' .State' );
                                    if( device.sensorState == true || device.sensorState == false ) {
                                        if( device.sensorState == true ) {
                                            $(el).find(".OneByTwoSensorMessage").html( I18n.JS_DEVICE_ALARM_STATUS_ALARM );
                                        }
                                        else {
                                            $(el).find(".OneByTwoSensorMessage").html( I18n.JS_DEVICE_ALARM_STATUS_IDLE );
                                        }
                                    }
                                    else {
                                        // don't change text on communication dropouts
                                    }

                                    if( device.sensorLastChanged ) {
                                        $('#SortableDevice_' + deviceId + ' .Log' ).find('.OneByTwoSensorMessage' ).html(
                                            Util.formatTimestamp( device.sensorLastChanged * 1000  )
                                        );
                                    }
                                }

                                if( undefined == json.data.error || undefined == json.data.error[ deviceId ] ) {
                                    $("#Device_" + deviceId + '_SensorValue .Value, #Device_' + deviceId + '_MeterCurrent .Value').html( device.sensorValue );
                                    $("#Device_" + deviceId + ' .Value').html( device.sensorValue );
                                    $("#Device_" + deviceId + '_MeterTotal .Value').html( device.totalValue );
                                }
                                else {
                                    // don't touch current value on errors
                                }

                                if( undefined == Control.wasChanged[ 'Device_' + deviceId ]
                                 || updateTime > Control.wasChanged [ 'Device_' + deviceId ]
                                ) {
                                    if( device.syncStatus == AjaxConst.SYNC_OK ) {
                                        Control.removeIndefinite( 'Device_' + deviceId );
                                        Control.setValue( 'Device_' + deviceId, device.value, device.state, device.dimension );
                                    }
                                    else if ( device.syncStatus == AjaxConst.SYNC_PENDING  ) {
                                        Control.setIndefinite( 'Device_' + deviceId );
                                        Control.setValue( 'Device_' + deviceId, device.value, device.state, device.dimension );
                                    }
                                    else if ( device.syncStatus == AjaxConst.SYNC_REMOTELY_CHANGED ) {
                                        Control.setValue( 'Device_' + deviceId, device.value, device.state, device.dimension );
                                        Control.removeIndefinite( 'Device_' + deviceId );
                                    }
                                }
                            }
                        }
                    }
                    UpdateDevices.lockToken = false;
                },
                error: function(json) {
                    $('#GatewayStatus').show();
                    UpdateDevices.lockToken = false;
                }
            });
        }

       UpdateDevices.initAll();
    },
    d:0
}

var Checkbox = {
    initAll:function(){
        $(".Checkbox").each(function(){Checkbox.init($(this))});
    },
    init:function(el){
        if(!el.hasClass('CheckboxHidden')) {
            el.addClass("CheckboxHidden");
            el.next().append('<div class="ColoredElementIcon CheckboxIcon"></div>');
            Checkbox.toggle(el);
            el.change(function(){
                Checkbox.toggle(el);
            });
        }
    },
    toggle:function(el){
        var checked=el.attr("checked");
        if(checked){
            el.next().removeClass("CheckboxLabel");
            el.next().addClass("CheckboxLabelChecked");
            el.next().children("div").addClass("CheckboxIconChecked");
        }
        else{
            el.next().removeClass("CheckboxLabelChecked");
            el.next().addClass("CheckboxLabel");
            el.next().children("div").removeClass("CheckboxIconChecked");
        }
    }
};

var Radio = {
    initAll:function(){
        $(".RadioList,.RadioListVertical").each(function(){Radio.initList($(this))});
    },
    init:function(el){
        el.addClass("RadioHidden");
        el.next().append('<div class="ColoredElementIcon RadioIcon"></div>');
        Radio.findChecked(el.parents('ol,ul'));
        el.change(function(){Radio.findChecked(el.parents('ol,ul'))});
    },
    initList:function(list){
        list.find('input').each(function(){
            Radio.init($(this));
        });
        Radio.findChecked(list);
    },
    setChecked:function(el){
        el.next().removeClass("RadioLabel");
        el.next().addClass("RadioLabelChecked");
        el.next().children("div").addClass("RadioIconChecked");
    },
    setUnchecked:function(el){
        el.next().removeClass("RadioLabelChecked");
        el.next().addClass("RadioLabel");
        el.next().children("div").removeClass("RadioIconChecked");
    },
    findChecked:function(list){
        list.find('input').each(function(){
            if($(this).attr('checked')){
                Radio.setChecked($(this));
            }else{
                Radio.setUnchecked($(this));
            }
        });
    }
};

Device = {
    turnOn:function(uid){
        $.ajax({
            type:"post",
            url: webroot+"/ajax/turn-on",
            data: {"uid":uid},
            success: function(data, textStatus){
            }
        });
    },
    turnOff:function(uid){
        $.ajax({
            type:"post",
            url: webroot+"/ajax/turn-off",
            data: {"uid":uid},
            success: function(data, textStatus){
            }
        });
    },
    dim:function(uid,level){
        $.ajax({
            type:"post",
            url: webroot+"/ajax/dim",
            data: {"uid":uid,"level":level},
            success: function(data, textStatus){
            }
        });
    },
    hideFromDashboard:function(el){
        setTimeout(function(){
            $(el).animate({opacity:0},200).animate({
                width:0
            }, 200, function(){$(this).remove()});
        }, 400);
    },
    controlDeviceOnload:function(p){
        var a=jQuery.url.attr("anchor");
        $("#Device_"+a).addClass("Selected",500);
        $(".DeviceNameTD").click(function(){
            var deviceId=Util.getIdFromDomId($(this).closest('tr').attr("id"));
            Util.loadMrT({
                url:webroot+'/ajax/mrt-device/'+p.deviceIdParamName+'/'+deviceId
            });
        });
        $(".ElementAction a").click(function(){
            var deviceId=Util.getIdFromDomId($(this).closest('tr').attr("id"));
            Util.loadMrT({
                url:webroot+'/ajax/mrt-device/'+p.deviceIdParamName+'/'+deviceId
            });
        });
        $(".ElementConsumption").click(function(){
            var deviceId=Util.getIdFromDomId($(this).closest('tr').attr("id"));
            Util.loadMrT({
                url:webroot+'/ajax/mrt-graph/'+p.deviceIdParamName+'/'+deviceId
            });
        });
    },
    deviceAdmin:function(operation, callback, params ){
        var defaultParam = {
            url:webroot+'/ajax/device-admin',
            data:{'deviceAdminOperation':operation},
            dataType:"json",
            cache:false,
            success:function(json){
                if(json.ok){
                    if($.isFunction(callback)){
                        callback(json);
                    }
                }
                else {
                    Device.showScanError();
                }
            },
            error:function(data) {
                Device.showScanError();
            }
        }
        $.extend( defaultParam, params );
        $.ajax( defaultParam );
    },
    deviceAdminEvent:function(event, callback, params ){
        var defaultParam = {
            url:webroot+'/ajax/device-admin',
            data:{'deviceAdminOperation':'sendEvent','event':event},
            dataType:"json",
            cache:false,
            success:function(json){
                if(json.ok){
                    if($.isFunction(callback)){
                        callback(json);
                    }
                }
                else {
                    Device.showScanError();
                }
            },
            error:function(data) {
                Device.showScanError();
            }
        }
        $.extend( defaultParam, params );
        $.ajax( defaultParam );
    },
    initScan:function(callback){
        UpdateDevices.addStarting = true;
        Device.deviceAdminEvent( DeviceAdminConst.EVENT_START_ADD, callback);
    },
    initRemove:function(callback){
        UpdateDevices.removeStarting = true;
        Device.deviceAdminEvent( DeviceAdminConst.EVENT_START_REMOVE, callback);
    },
    addDetected:function(callback){
        Device.deviceAdmin('addDetected', callback);
    },
    removeDeleted:function(callback){
        Device.deviceAdmin('removeDeleted', callback);
    },
    scanAbort:function() {
        //$('#DeviceScanRunning').hide();
        //$('#DeviceRemoveRunning').hide();
        Device.deviceAdminEvent( DeviceAdminConst.EVENT_CANCEL );
    },
    showScanError:function(){
        $('#DeviceScanError').show();
        $("#DeviceScanLoader").slideUp();
        $('#DeviceScanMessageWrap').slideDown();
    },
    d:0
}

var DeviceGroup = {
    remove:function(p){
        Util.showLoader();
        $.ajax({
            url:webroot+'/ajax/group',
            cache:false,
            data:{'groupOperation':'groupDelete','groupId':p.groupId},
            success:function(json){
                Util.hideLoader();
                try{
                    if(json.code==0){
                        if(p.hideOnDelete){
                            DeviceGroup.hideFromList(p.groupId);
                        }
                    }
                }catch(e){
                }
            }
        });
    },
    hideFromList:function(groupId){
        var el=$('#DeviceGroup_'+groupId);
        setTimeout(function(){
            $(el).animate({opacity:0},{
                duration:200,
                complete:function(){
                    $('#DeviceGroup_'+groupId+' .HideOnRemove').remove();
                    $('#DeviceGroup_'+groupId+' td').animate({height:0},{
                        duration:200,
                        complete:function(){
                            $(el).remove();
                        }
                    });
                }
            });
        }, 400);
    },
    registerDelete:function(selector){
        $(selector).click(function(){
            var gId=$(this).closest('tr').attr('id').replace('DeviceGroup_','');
            var groupName = $('#DeviceGroup_'+gId+' .DeviceGroupName').html();
            var deleteConfirmed = confirm(Util.sprintf(I18n.JS_CONFIRM_GROUP_DELETION, groupName));
            if(deleteConfirmed){
                DeviceGroup.remove({groupId:gId,hideOnDelete:true});
            }
        });
    },
    addToList:function(name,html){
        var groupName = [];
        $('.DeviceGroupName').each(function(){
           groupName.push($(this).html());
        });
        var pos = -1;
        $.each(groupName,function(k,v){
            if(name.toLowerCase()<v.toLowerCase()){
                pos=k;
                return false;
            }
        });
        if(pos==-1){
            $('#DeviceGroupTable').append(html);
        }else{
            $('#DeviceGroupTable tr').eq(pos).before(html);
        }
    },
    add:function(){
        Util.loadMrT({
            url:webroot+'/ajax/mrt-group'
        });
    },
    edit:function(id){
        Util.loadMrT({
            url:webroot+'/ajax/mrt-group/?'+CommunicationParameters.PARAMETER_NAME_GROUP_ID+'='+id
        });
    }
}

var SavingsAdvice = {
    getRandom:function(callback){
        $.ajax({
            url: webroot+'/ajax/get-savings-advice/',
            cache: false,
            success: function(r){
                if($.isFunction(callback)) {
                    callback(r);
                }
            }
        });
    },
    bindClick:function(){
        $('.SavingsAdvice a').click(function(){
            Util.showLoader();
            var toReplace=$(this).closest('.SavingsAdvice').find('.SavingsAdviceTextInner');
            SavingsAdvice.getRandom(function(r){
                toReplace.html(r);
                Util.hideLoader();
            });
        });
    }
}

var DeviceAdmin = {
    sendScanEvent:function(event){
        Util.showLoader();
        $.ajax({
            url: webroot+'/ajax/device-admin/',
            data: {'deviceAdminOperation': 'sendEvent', 'event': event},
            success: function(r) {
                Util.hideLoader();
            }
        });
    }
}

$(document).ready(function(){
    $('#Theme').click(function() {
        var value = $.cookie('theme');

        if (value == 'default') {
            $.cookie('theme','lilac',{expires: 365, path: '/'});
            $('.dummy').attr('src','/images/female-genius.png');
        } else {
            $.cookie('theme','default',{expires: 365, path: '/'});
            $('.dummy').attr('src','/images/einstellung-genius.png');
        }
        location.reload();
    });
    
    if( null != I18n ) {
        $.iButton.setDefaults({labelOn:I18n.IBUTTON_LABEL_ON, labelOff:I18n.IBUTTON_LABEL_OFF, resizeContainer: false});
    }
    Checkbox.initAll();
    Radio.initAll();
});

/* JQUERY PLUGINS */

/*
* @Copyright (c) 2010 Ricardo Andrietta Mendes - eng.rmendes@gmail.com
*
*/
jQuery.fn.numberFormat = function(numero, params){ //indica o nome do plugin que serÃ¡ criado com os parametros a serem informados
    //parametros default
    var sDefaults = {
        numberOfDecimals: 2,
        decimalSeparator: ',',
        thousandSeparator: '',
        symbol: ''
    }

    //funÃ§Ã£o do jquery que substitui os parametros que nÃ£o foram informados pelos defaults
    var options = jQuery.extend(sDefaults, params);

    //CORPO DO PLUGIN
    var number = numero;
    var decimals = options.numberOfDecimals;
    var dec_point = options.decimalSeparator;
    var thousands_sep = options.thousandSeparator;
    var currencySymbol = options.symbol;

    var exponent = "";
    var numberstr = number.toString ();
    var eindex = numberstr.indexOf ("e");
    if (eindex > -1){
        exponent = numberstr.substring (eindex);
        number = parseFloat (numberstr.substring (0, eindex));
    }

    if (decimals != null){
        var temp = Math.pow (10, decimals);
        number = Math.round (number * temp) / temp;
    }
    var sign = number < 0 ? "-" : "";
    var integer = (number > 0 ?
      Math.floor (number) : Math.abs (Math.ceil (number))).toString ();

    var fractional = number.toString ().substring (integer.length + sign.length);
    dec_point = dec_point != null ? dec_point : ".";
    fractional = decimals != null && decimals > 0 || fractional.length > 1 ?
               (dec_point + fractional.substring (1)) : "";
    if (decimals != null && decimals > 0){
        for (i = fractional.length - 1, z = decimals; i < z; ++i)
          fractional += "0";
    }

    thousands_sep = (thousands_sep != dec_point || fractional.length == 0) ?
                  thousands_sep : null;
    if (thousands_sep != null && thousands_sep != ""){
        for (i = integer.length - 3; i > 0; i -= 3)
          integer = integer.substring (0 , i) + thousands_sep + integer.substring (i);
    }

    if (options.symbol == ''){
        return sign + integer + fractional + exponent;
    }
    else{
        return currencySymbol + ' ' + sign + integer + fractional + exponent;
    }
}

/*
 * JQuery Random Plugin
 * by Christian Bruun - 23. jan 2009
 */
jQuery.extend({
    random: function(X) {
        return Math.floor(X * (Math.random() % 1));
    },
    randomBetween: function(MinV, MaxV) {
      return MinV + jQuery.random(MaxV - MinV + 1);
    }
});


/* German initialisation for the jQuery UI date picker plugin. */
/* Written by Milian Wolff (mail@milianw.de). */
jQuery(function($){
    if($.datepicker){
        $.datepicker.regional['de'] = {
            dateFormat: 'dd.mm.yy',
            firstDay: 1,
            isRTL: false,
            showMonthAfterYear: false,
            yearSuffix: ''
        };
        $.datepicker.setDefaults($.datepicker.regional['de']);

        if (I18n && typeof I18n !== 'undefined') {
            $.datepicker.translations = {
                closeText: I18n.JS_DATEPICKER_CLOSE_TEXT,
                prevText: I18n.JS_DATEPICKER_PREV_TEXT,
                nextText: I18n.JS_DATEPICKER_NEXT_TEXT,
                currentText: I18n.JS_DATEPICKER_CURRENT_TEXT,
                monthNames: [
                    I18n.JS_DATEPICKER_MONTH_NAME_JAN,
                    I18n.JS_DATEPICKER_MONTH_NAME_FEB,
                    I18n.JS_DATEPICKER_MONTH_NAME_MAR,
                    I18n.JS_DATEPICKER_MONTH_NAME_APR,
                    I18n.JS_DATEPICKER_MONTH_NAME_MAY,
                    I18n.JS_DATEPICKER_MONTH_NAME_JUN,
                    I18n.JS_DATEPICKER_MONTH_NAME_JUL,
                    I18n.JS_DATEPICKER_MONTH_NAME_AUG,
                    I18n.JS_DATEPICKER_MONTH_NAME_SEP,
                    I18n.JS_DATEPICKER_MONTH_NAME_OCT,
                    I18n.JS_DATEPICKER_MONTH_NAME_NOV,
                    I18n.JS_DATEPICKER_MONTH_NAME_DEC
                ],
                monthNamesShort: [
                    I18n.JS_DATEPICKER_MONTH_NAME_SHORT_JAN,
                    I18n.JS_DATEPICKER_MONTH_NAME_SHORT_FEB,
                    I18n.JS_DATEPICKER_MONTH_NAME_SHORT_MAR,
                    I18n.JS_DATEPICKER_MONTH_NAME_SHORT_APR,
                    I18n.JS_DATEPICKER_MONTH_NAME_SHORT_MAY,
                    I18n.JS_DATEPICKER_MONTH_NAME_SHORT_JUN,
                    I18n.JS_DATEPICKER_MONTH_NAME_SHORT_JUL,
                    I18n.JS_DATEPICKER_MONTH_NAME_SHORT_AUG,
                    I18n.JS_DATEPICKER_MONTH_NAME_SHORT_SEP,
                    I18n.JS_DATEPICKER_MONTH_NAME_SHORT_OCT,
                    I18n.JS_DATEPICKER_MONTH_NAME_SHORT_NOV,
                    I18n.JS_DATEPICKER_MONTH_NAME_SHORT_DEC
                ],
                dayNames: [
                    I18n.JS_DATEPICKER_DAY_NAME_SUN,
                    I18n.JS_DATEPICKER_DAY_NAME_MON,
                    I18n.JS_DATEPICKER_DAY_NAME_TUE,
                    I18n.JS_DATEPICKER_DAY_NAME_WED,
                    I18n.JS_DATEPICKER_DAY_NAME_THU,
                    I18n.JS_DATEPICKER_DAY_NAME_FRI,
                    I18n.JS_DATEPICKER_DAY_NAME_SAT
                ],
                dayNamesShort: [
                    I18n.JS_DATEPICKER_DAY_NAME_SHORT_SUN,
                    I18n.JS_DATEPICKER_DAY_NAME_SHORT_MON,
                    I18n.JS_DATEPICKER_DAY_NAME_SHORT_TUE,
                    I18n.JS_DATEPICKER_DAY_NAME_SHORT_WED,
                    I18n.JS_DATEPICKER_DAY_NAME_SHORT_THU,
                    I18n.JS_DATEPICKER_DAY_NAME_SHORT_FRI,
                    I18n.JS_DATEPICKER_DAY_NAME_SHORT_SAT
                ],
                dayNamesMin: [
                    I18n.JS_DATEPICKER_DAY_NAME_SHORT_SUN,
                    I18n.JS_DATEPICKER_DAY_NAME_SHORT_MON,
                    I18n.JS_DATEPICKER_DAY_NAME_SHORT_TUE,
                    I18n.JS_DATEPICKER_DAY_NAME_SHORT_WED,
                    I18n.JS_DATEPICKER_DAY_NAME_SHORT_THU,
                    I18n.JS_DATEPICKER_DAY_NAME_SHORT_FRI,
                    I18n.JS_DATEPICKER_DAY_NAME_SHORT_SAT
                ],
                weekHeader: I18n.JS_DATEPICKER_WEEK_HEADER
            };
            $.datepicker.setDefaults($.datepicker.translations);
        }
    }


    if($.timepicker){

        $.timepicker.regional['de'] = {
            ampm: false,
            timeFormat: 'hh:mm tt',
            minDate: new Date(2011, 1, 1, 0, 0),
            maxDate: new Date(2011, 1, 2, 23, 59)
        };

        $.timepicker.setDefaults($.timepicker.regional['de']);

        if (typeof I18n !== 'undefined') {
            $.timepicker.translations = {
                currentText: I18n.JS_TIME_PICKER_CURRENT_TEXT,
                closeText: I18n.JS_TIMEPICKER_CLOSE_TEXT,
                timeText: I18n.JS_TIMEPICKER_TIME_TEXT,
                hourText: I18n.JS_TIMEPICKER_HOUR_TEXT,
                minuteText: I18n.JS_TIMEPICKER_MINUTE_TEXT,
                secondText: I18n.JS_TIMEPICKER_SECOND_TEXT,
                timezoneText: I18n.JS_TIMEPICKER_TIMEZONE_TEXT,
                timeOnlyTitle: I18n.JS_TIMEPICKER_ONLY_TITLE

            };
            $.timepicker.setDefaults($.timepicker.translations);
        }
    }

});

/*
  PHP style date() plugin
  Call in exactly the same way as you do the "date" command in PHP
  e.g. s = $.PHPDate("l, jS F Y", dtDate);

  License:
  PHPDate 1.0 jQuery Plugin

  Copyright (c) 2008 Jon Combe (http://joncom.be)

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation
  files (the "Software"), to deal in the Software without
  restriction, including without limitation the rights to use,
  copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the
  Software is furnished to do so, subject to the following
  conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  OTHER DEALINGS IN THE SOFTWARE.
*/

(function($) {
  var aDays = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];
  var aMonths = ["January","February","March","April","May","June","July","August","September","October","November","December"];

  // main function
  $.PHPDate = function(sString, dtDate) {
    var sElement = "";
    var sOutput = "";

    // we can cheat with "r"...
    sString = sString.replace(/r/g, "D, j M Y H;i:s O");

    // loop through string
    for (var i = 0; i < sString.length; i++) {
      sElement = sString.charAt(i);
      switch (sElement) {
        case "a":sElement = AMPM(dtDate.getHours());break;
        case "c":
          sElement = (dtDate.getFullYear() + "-" +
                      AddLeadingZero(dtDate.getMonth()) + "-" +
                      AddLeadingZero(dtDate.getDate()) + "T" +
                      AddLeadingZero(dtDate.getHours()) + ":" +
                      AddLeadingZero(dtDate.getMinutes()) + ":" +
                      AddLeadingZero(dtDate.getSeconds()));
          var sTemp = dtDate.toString().split(" ")[5];
          if (sTemp.indexOf("-") > -1) {
            sElement += sTemp.substr(sTemp.indexOf("-"));
          } else if (sTemp.indexOf("+") > -1) {
            sElement += sTemp.substr(sTemp.indexOf("+"));
          } else {
            sElement += "+0000";
          }
          break;
        case "d":sElement = AddLeadingZero(dtDate.getDate());break;
        case "g":sElement = TwelveHourClock(dtDate.getHours());break;
        case "h":sElement = AddLeadingZero(TwelveHourClock(dtDate.getHours()));break;
        case "i":sElement = AddLeadingZero(dtDate.getMinutes());break;
        case "j":sElement = dtDate.getDate();break;
        case "l":sElement = aDays[dtDate.getDay()];break;
        case "m":sElement = AddLeadingZero(dtDate.getMonth() + 1);break;
        case "n":sElement = dtDate.getMonth() + 1;break;
        case "o":(new Date(FirstMonday(dtDate.getFullYear())) > dtDate) ? sElement = (dtDate.getFullYear() - 1) : sElement = dtDate.getFullYear();break;
        case "s":sElement = AddLeadingZero(dtDate.getSeconds());break;
        case "t":
          var dtTemp = new Date(dtDate.valueOf());
          dtTemp.setMonth(dtTemp.getMonth() + 1)
          dtTemp.setDate(0);
          sElement = dtTemp.getDate();
          break;
        case "u":sElement = dtDate.getMilliseconds();break;
        case "w":sElement = dtDate.getDay();break;
        case "y":sElement = dtDate.getFullYear().toString().substr(2, 2);break;
        case "z":
          var dtFirst = new Date(dtDate.getFullYear(), 0, 1, 0, 0, 0, 0);
          var dtLast = new Date(dtDate.getFullYear(), dtDate.getMonth(), dtDate.getDate(), 0, 0, 0, 0);
          sElement = Math.round((dtLast.valueOf() - dtFirst.valueOf()) / 1000 / 60 / 60/ 24);
          break;
        case "A":sElement = AMPM(dtDate.getHours()).toUpperCase();break;
        case "B":
          sElement = Math.floor(((dtDate.getHours() * 60 * 60 * 1000) +
          (dtDate.getMinutes() * 60 * 1000) +
          (dtDate.getSeconds() * 1000) +
          (dtDate.getMilliseconds())) / 86400);
          break;
        case "D":sElement = aDays[dtDate.getDay()].substr(0, 3);break;
        case "F":sElement = aMonths[dtDate.getMonth()];break;
        case "G":sElement = dtDate.getHours();break;
        case "H":sElement = AddLeadingZero(dtDate.getHours());break;
        case "I":
          var dtTempFirst = new Date(dtDate.getFullYear(), 0, 1);
          var dtTempLast = new Date(dtDate.getFullYear(), dtDate.getMonth(), dtDate.getDate());
          var iDaysDiff = (dtTempLast.valueOf() - dtTempFirst.valueOf()) / 1000 / 60 / 60 / 24;
          (iDaysDiff == Math.round(iDaysDiff)) ? sElement = 0 : sElement = 1;
          break;
        case "L":((new Date(dtDate.getFullYear(), 2, 0)).getDate() == 29) ? sElement = 1 : sElement = 0;break;
        case "M":sElement = aMonths[dtDate.getMonth()].substr(0, 3);break;
        case "N":(dtDate.getDay() == 0) ? sElement = 7 : sElement = dtDate.getDay();break;
        case "O":
          var sTemp = dtDate.toString().split(" ")[5];
          if (sTemp.indexOf("-") > -1) {
            sElement = sTemp.substr(sTemp.indexOf("-"));
          } else if (sTemp.indexOf("+") > -1) {
            sElement = sTemp.substr(sTemp.indexOf("+"));
          } else {
            sElement = "+0000";
          }
          break;
        case "P":
          var sTemp = dtDate.toString().split(" ")[5];
          if (sTemp.indexOf("-") > -1) {
            var aTemp = sTemp.substr(sTemp.indexOf("-") + 1).split("");
            sElement = ("-" + aTemp[0] + aTemp[1] + ":" + aTemp[2] + aTemp[3]);
          } else if (sTemp.indexOf("+") > -1) {
            var aTemp = sTemp.substr(sTemp.indexOf("+") + 1).split("");
            sElement = ("+" + aTemp[0] + aTemp[1] + ":" + aTemp[2] + aTemp[3]);
          } else {
            sElement = "+00:00";
          }
          break;
        case "S":sElement = DateSuffix(dtDate.getDate());break;
        case "T":
          sElement = dtDate.toString().split(" ")[5];
          if (sElement.indexOf("+") > -1) {
            sElement = sElement.substr(0, sElement.indexOf("+"));
          } else if (sElement.indexOf("-") > -1) {
            sElement = sElement.substr(0, sElement.indexOf("-"));
          }
          break;
        case "U":sElement = Math.floor(dtDate.getTime() / 1000);break;
        case "W":
          var dtTempFirst = new Date(FirstMonday(dtDate.getFullYear()));
          var dtTempLast = new Date(dtDate.getFullYear(), dtDate.getMonth(), dtDate.getDate());
          sElement = Math.ceil(Math.round((dtTempLast.valueOf() - dtTempFirst.valueOf()) / 1000 / 60 / 60/ 24) / 7);
          break;
        case "Y":sElement = dtDate.getFullYear();break;
        case "Z":
          (dtDate.getTimezoneOffset() < 0) ? sElement = Math.abs(dtDate.getTimezoneOffset() * 60) : sElement = (0 - (dtDate.getTimezoneOffset() * 60));
          break;
      }
      sOutput += sElement.toString();
      }
    return sOutput;
  }

  // add leading zero
  function AddLeadingZero(iValue) {
    if (iValue < 10) {
      iValue = ("0" + iValue);
    }
    return iValue;
  }

  // Ante meridiem and Post meridiem
  function AMPM(iHours) {
    if (iHours > 11) {
      return "pm";
    } else {
      return "am";
    }
  }

  // date suffix
  function DateSuffix(iDay) {
    var sSuffix = "th";
    switch (parseInt(iDay)) {
      case 1:
      case 21:
      case 31:
        sSuffix = "st";
        break;
      case 2:
      case 22:
        sSuffix = "nd";
        break;
      case 3:
      case 23:
        sSuffix = "rd";
    }
    return sSuffix;
  }

  // find the first Monday in a given year (for ISO 8601 dates)
  function FirstMonday(iYear) {
    var dtTemp = new Date(iYear, 0, 1);
    while (dtTemp.getDay() != 1) {
      dtTemp.setDate(dtTemp.getDate() + 1);
    }
    return dtTemp.valueOf();
  }

  // 12-Hour clock
  function TwelveHourClock(iHours) {
    if (iHours == 0) {
      iHours = 24;
    } else if (iHours > 12) {
      iHours -= 12;
    }
    return iHours;
  }
})(jQuery);

