/* -----
   Material Design JS for ioBroker.vis
   (c) 2017 Uhula, MIT License
   https://github.com/Uhula/ioBroker-Material-Design-Style
   V1.7 28.12.2017
   o Korrektur mdui-lnav/rnav. Funktionierte mit mdui-toggle nicht korrekt  
   V1.6 16.10.2017 
   O _toggleFullscreen geändert, damit die function auch im ioBroker
                   fullscreen Mode funktioniert
   o Delegator-Eventhandler für body gesetzt (bisher #vis_container, wirkten dann aber in Dialogen nicht)
   V1.5 11.10.2017 
   o MDUI.handleTables fertig
   V1.3 24.09.2017 
   + MDUI.handleTables hinzu (in Entwicklung)
   V1.0 01.09.2017
   ----- */

// Zur sicheren CSS-Erkennung der Runtime eine CSS-Klasse anlegen
document.documentElement.className +=  " mdui-runtime";

// Überprüfen ob touch zur Verfügung steht und entsprechend eine 
// CSS Klasse touch bzw no-touch erzeugen 
document.documentElement.className += 
    (("ontouchstart" in document.documentElement) ? " mdui-touch" : " mdui-notouch");


/* -----
   MDUI
   ----- 
   Sammlung von JS-Funktionen für das Material Design
   (c) 2017 Uhula, MIT License
*/

var MDUI = (function () {


var isSubtreeModified = false;

// liefert den suffix einer gegeben class zurück-Navigieren
// Bsp: mdui-target-w00002 -> w00002
//      mdui-zoom-to-200 -> 200
function _getClassSuffix( $ele, classname ) {
    var suf = "";
    if ($ele) {
        var c = $ele.attr( "class" );
        suf = c.substr(c.indexOf(classname)+classname.length,1000)+" ";
        suf = suf.substr(0,suf.indexOf(" "));
    }
    return suf;    
}

//
function _getGroupID( ele ) { return _getClassSuffix(ele, "mdui-group-" ); }
//
function _getTargetID( ele ) { return _getClassSuffix(ele, "mdui-target-" ); }

//
function _getScrollbarWidth() {
    var $outer = $('<div>').css({visibility: 'hidden', width: 100, overflow: 'scroll'}).appendTo('body'),
        widthWithScroll = $('<div>').css({width: '100%'}).appendTo($outer).outerWidth();
    $outer.remove();
    return 100 - widthWithScroll;
}
//
function _getScrollbarHeight() {
    var $outer = $('<div>').css({visibility: 'hidden', height: 100, overflow: 'scroll'}).appendTo('body'),
        heightWithScroll = $('<div>').css({height: '100%'}).appendTo($outer).outerHeight();
    $outer.remove();
    return 100 - heightWithScroll;
}

function _formatDatetime(date, format) {
    function fill(comp) {
        return ((parseInt(comp) < 10) ? ('0' + comp) : comp)
    }
        
    var months = ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'];
    var d = format;
    var o = {
            "y+": date.getFullYear(), // year
            "m+": fill(date.getMonth()+1), //month
            "M+": months[date.getMonth()], //month
            "d+": fill(date.getDate()), //day
            "H+": fill((date.getHours() > 12) ? date.getHours() % 12 : date.getHours()), //hour
            "h+": fill(date.getHours()), //hour
            "n+": fill(date.getMinutes()), //minute
            "s+": fill(date.getSeconds()), //second
            "S+": fill(date.getMilliseconds()), //millisecond,
            "b+": (date.getHours() >= 12) ? 'PM' : 'AM'
        };
    for (var k in o) {
        if (new RegExp("(" + k + ")").test(format)) {
            d = d.replace(RegExp.$1, o[k]);
        }
    }
    return d;
}



// alle Elemente mit class "mdui-group-XXX" togglen, in denen 
// XXX aus class "mdui-group-XXX" des ele ist UND
// alle Elemente mit class "mdui-target-XXX" togglen, in denen 
// XXX aus class "mdui-target-XXX" des ele ist
function _toggleVisibility( $ele ) {
    $ele.toggleClass("ui-state-active");
    var id = _getGroupID( $ele );
    if (id!=="") 
        $("[class*='mdui-group-"+id+"']").not("[class*='mdui-toggle']").each( function (index) {
            $(this).toggleClass("mdui-hide");
        });    
    id = _getTargetID( $ele );
    if (id!=="") 
        $( "[class*='mdui-target-"+id+"']").not("[class*='mdui-toggle']").each( function (index) {
            $(this).toggleClass("mdui-hide");
        });
}

// das in ele class \"mdui-target-XXX\" angegeben Element mit der id \"XXX\"  wird 
// - fullscreen angezeigt, wenn es noch nicht fullscreen ist
// - wieder normal angezeigt, wenn es fullscreen ist
function _toggleFullscreen( $ele ){
    if (!$ele) return;
    var $target = $ele.closest(".vis-view");
    if (!$target) return;
    var styleold = $target.attr("styleold");
    if (styleold) {
        $target.attr("style",styleold);
        $target.removeAttr("styleold");
        $target.appendTo(".mdui-id-"+$target.attr("id"));
        } else {
            $target.parent().addClass("mdui-id-"+$target.attr("id"));
            $target.attr("styleold",$target.attr("style"));
            $target.attr("style","position:fixed; left:0; top:0; width:100%; height:100%; z-index: 2147483647 !important;background:#212121 !important; ");
            $target.appendTo( "body" );
            //$target.appendTo( "body #vis_container" );
            }
}


// ele muss class Einträge für das Target und den Skalierungsmodus haben
// "mdui-target-(id) mdui-scale-(scalemode)" 
// id: Ziel-Element mit id=id, welches ein zu skalierendes img enthält
// scalemode: fit / hfit / vfit / in / out / (number)
// number: Zahl in %
function _scale( ele ) {
    var id = _getTargetID( ele );
    var $img = $( "#"+id+" img" );
    if ($img) {
        var scale = _getClassSuffix(ele, "mdui-scale-" );
        $img.width("1px"); // Scrollbars entfernen um die echte Höhe zu bekommen
        $img.height("1px");
        var dim = {
            pw : $img.parent().width(), 
            ph : $img.parent().height(), 
            w  : $img[0].naturalWidth, 
            h  : $img[0].naturalHeight
        };
        switch(scale) {
            case "fit":
                if (dim.pw / dim.w < dim.ph / dim.h ) scale = dim.pw / dim.w;  
                else scale = dim.ph / dim.h;
                break;
            case "hfit":
                if (dim.pw / dim.w < dim.ph / dim.h ) scale = dim.pw / dim.w;
                else scale = (dim.pw - _getScrollbarWidth() - 4  ) / dim.w;
                break;
            case "vfit":
                if ( dim.pw / dim.w > dim.ph / dim.h ) scale = dim.ph / dim.h;
                else scale = (dim.ph - _getScrollbarHeight() - 4  ) / dim.h;
                break;
            case "in":
            case "out":
                var old = $img.attr( "style" );
                old = old.substr(old.indexOf("scale(")+6,20);  
                old = old.substr(0,old.indexOf(")"));  
                if (old * 1==0) scale = 1;
                else if (scale=="in") scale = old * 1.41;
                     else scale = old / 1.41;
                break;
            default:
                if (scale<=0 || scale>10000)
                    scale = 100;
                scale = scale/100;
        }
        scale = Math.round(scale*100)/100;
        $img.attr( "style", "position:absolute;top:0;left:0;transform-origin:0 0;transition: transform 0.3s ease-out; transform:scale("+scale+");" );
        }
}

// ersetzt im src-Attribute des Unter-Elements von (id) den "&range=& 
// durch den Wert des in ele angegebenen (span). Für flot-Diagramme
// "mdui-target-(id) mdui-timespan-(span)" 
// id: Ziel-Element mit id=id, welches das flot (src) enthält
// span: inc / dec / (number)
// number: Zahl in Minuten
function _timespan( ele ) {
    var id = _getTargetID( ele );
    var target = $( "#"+id+" [src]" );
    if (target) {
        var timespan = _getClassSuffix(ele, "mdui-timespan-" );
        var src = target.attr( "src" );
        var min = src.substr(src.indexOf("&range=")+7,20);  
        min = min.substr(0,min.indexOf("&"));  
        switch(timespan) {
            case "inc":
                min = min * 2;
                break;
            case "dec":
                min = min / 2;
                break;
            default:
                if ( timespan<=0 )
                    timespan = 1440;
                min = timespan;
        }
        src = src.replace(/&range=[0-9]*&/g, "&range="+min+"&");
        target.attr("src",src);
    }
}

/*  */
function _resetTable( $ele, $table ) {
    $ele.removeClass("mdui-table-tile");
    $ele.removeClass("mdui-table-card");
    $ele.removeClass("mdui-table-list");
    $table.find("tbody>tr").each( function(index) {
        $(this).width("auto");
        $(this).height("auto");
        $(this).find("td").each( function(index) {
            $(this).attr("labelth","");
        });  
    });
}

/*  */
function _handleTable( $ele, $table, opt ) {

    function setColWidth( colwidth ) {
        $table.find("tbody>tr").each( function(index) {
            $(this).outerWidth(colwidth);
        });
    }
    function setColHeight() {
        var height = 0;
        $table.find("tbody>tr").each( function(index) {
            if ($(this).height() > height ) height = $(this).height();
        });
        if ( height > 0 )
            $table.find("tbody>tr").each( function(index) {
                $(this).height( height );
            });
    }
    
    var innerWidth = $ele.innerWidth();

    _resetTable($ele, $table);
    $ele.addClass("mdui-table-"+opt.type);
    if (opt.label) {
        // Zellen mit Labels aus <th> ergänzen ?    
        var labels = [];
        $table.find("thead>tr>th").each( function(index) {
            labels[index] = $(this).text();
        });
        $table.find("tbody>tr").each( function(index) {
            $(this).find("td").each( function(index) {
                if (index < labels.length) 
                    $(this).attr("labelth",labels[index]);
            });  
        });
    }

    if (opt.colwidth>1) setColWidth(opt.colwidth);
    if (opt.colwidth>2) setColHeight();

    return true;    
}


/* Alle mdui-table durchlaufen und überprüfen, ob die minimale Width erreicht
wurde um sie in den responsive State zu überführen 
mdui-table-(mode)(-opt1)(-opt2)...(-optn)
mdui-table-ascard-r600-w200-l */
function _handleTables( ) {
    $("[class*='mdui-table ']").each( function (index) {
        var $ele = $(this);
        var $table;
        $table = $ele;
        if (!$table.is("table")) $table=$table.find("table");
        if (!$table.is("table")) return true; // next each 
        
        var innerWidth = $ele.innerWidth();
        var classes = $ele.attr("class")
            .split(" ")
            .filter( function ( ele ) { 
                    return  (ele.indexOf("mdui-table-ascard") > -1)
                         || (ele.indexOf("mdui-table-astile") > -1)
                         || (ele.indexOf("mdui-table-aslist") > -1); });
        var opts = [];
        var opt;
        for (var i = 0; i < classes.length; i++) {
            opts[i] = [];
            opts[i].reswidth = 9999;
            opts[i].colwidth = 0;
            opts[i].label = false;
            opts[i].type = classes[i].substr(13,4); 
            opt = classes[i].substr(18,200).split("-"); 
            for (var j = 0; j < opt.length; j++) {
                switch(opt[j][0]) {
                case "r":
                    opts[i].reswidth = parseInt(opt[j].substr(1,5));
                    break;
                case "w":
                    opts[i].colwidth = parseInt(opt[j].substr(1,5));
                    break;
                case "c":
                    opts[i].colwidth = parseInt(opt[j].substr(1,5));
                    if (opts[i].colwidth>0) opts[i].colwidth = (innerWidth-_getScrollbarWidth()-8) / opts[i].colwidth;
                    break;
                case "l":
                    opts[i].label = true;
                    break;
                default:    
                }                       
            }
        }
        opts.sort(function(a, b){return a.reswidth-b.reswidth});
//console.log(opts);
        if (opts.length === 0) return true; // next each 
        var handled = false;
        for (i = 0; i < opts.length; i++) {
            if ( innerWidth < opts[i].reswidth )
               handled = _handleTable( $ele, $table, opts[i]);
            if (handled) break;   
        }
        if (!handled) _resetTable($ele, $table);
    }); 

}




// DOM SubTree-Änderungen einmalig alle 500ms auswerten (diese Events werden 
// u.U. 1000-fach gefeuert und müssen deswegen verzögert ausgeführt werden)
function _onSubTreeModified( $ele ) {
    if (!isSubtreeModified) {
        isSubtreeModified = true;
        setTimeout(function () {
            _handleTables();
            isSubtreeModified=false;
        }, 500);
    }
}

return {
    toggleVisibility: _toggleVisibility,
    toggleFullscreen: _toggleFullscreen,
    scale: _scale,
    timespan: _timespan,
    handleTables: _handleTables,
    onSubTreeModified : _onSubTreeModified
};

})();


// Eventhandler für body-Delegators setzen (früher:#vis_container) 
setTimeout(function () {
    // click-Event für das left-nav Element zum Öffnen
    $("body").on( "click", ".mdui-lnavbutton", function() { 
        $( ".mdui-lnav" ).addClass( "mdui-lnav-open" );
    } );
    // click-Event für die left-nav zum Schließen
    $("body").on( "click", ".mdui-lnav", function() { 
        $( ".mdui-lnav" ).removeClass( "mdui-lnav-open" ); 
    } );
    // click-Event für das right-nav Element zum Öffnen
    $("body").on( "click", ".mdui-rnavbutton", function() { 
        $( ".mdui-rnav" ).addClass( "mdui-rnav-open" );
    } );
    // click-Event für die right-nav zum Schließen
    $("body").on( "click", ".mdui-rnav", function() { 
        $( ".mdui-rnav" ).removeClass( "mdui-rnav-open" ); 
    } );

    // click-Eventhandler für "mdui-scale-" setzen
    $("body").on( "click", "[class*='mdui-scale-']", function(event) { 
        MDUI.scale( $(this) );
    } );

    // click-Handler für "mdui-toggle"  
    $("body").on( "click", ".mdui-toggle", function(event) { 
        event.preventDefault();
        event.stopImmediatePropagation();
        MDUI.toggleVisibility( $(this) );
    } );

    // click-Handler für "mdui-fullscreen" 
    $("body").on( "click", ".mdui-fullscreen", function(event) { 
        MDUI.toggleFullscreen( $(this) );
    } );

    // click-Handler für "mdui-timepsan-" 
    $("body").on( "click", "[class*='mdui-timespan-']", function(event) { 
        MDUI.timespan( $(this) );
    } );

    $( window ).on("resize", function() {
      MDUI.handleTables();
    });

    // Überwachen des #vis_containers auf Änderungen (z.B. wenn views nachgeladen
    // werden)
    $( "#vis_container" ).on( "DOMSubtreeModified", function(event) { 
        MDUI.onSubTreeModified( $(this) );
    } );
    // für den ersten load einmal aufrufen
    MDUI.onSubTreeModified( );

}, 1000);