/**
 * linksBox targets the UL element designed to contain offline page links
 * @type {*|jQuery|HTMLElement}
 */
const linksBox = $( 'body.offline ul' ) ;

/**
 * offlineLocations: Store locations and URLs to these locations we wish to
 * show the user when offline.  These links will not show if the page is not cached.
 * @type {*[]}
 */
const offlineLocations = [
    {
        urls: [ "/home/dashboard", "/home" , "/ilp" ] ,
        label: "CEDAR Dashboard"
    } ,

    /* Student/Parent pages */

    {
        urls: [ "/ilp/details/QRCode" ] ,
        label: "Your QR Code"
    } ,
    {
        urls: [ "/ilp/markbook" ] ,
        label: "Markbook Summary"
    } ,
    {
        urls: [ "/ilp/markbook/btec" ] ,
        label: "BTEC Summary"
    } ,
    {
        urls: [ "/ilp/exams/timetable" ] ,
        label: "Exam Timetable"
    } ,
    {
        urls: [ "/ilp/exams/mocktimetable" ] ,
        label: "Other Exams Timetable"
    } ,
    {
        urls: [ "/ilp/exam/results" ] ,
        label: "Exams Results"
    } ,
    {
        urls: [ "/ilp/learningplan" ] ,
        label: "Learning Plan"
    } ,
    {
        urls: [ "/ilp/timetable" ] ,
        label: "Student Timetable"
    } ,

    /* Staff pages */

    {
        urls: [ "/home/my/timetable" ] ,
        label: "Lesson Timetable"
    } ,
    {
        urls: [ "/home/notepad" ] ,
        label: "Notepad"
    }
] ;

// Prevent animations kicking off immediately to initial positions
setTimeout( () => $('body').addClass( 'loaded' ), 250 );

// Setup the timer to check for our connection status every few seconds
setInterval( () => checkConnection() , 5000 ) ;

// Kick off the offline links population, filling in links only if we have them cached
populateOfflineLinks() ;

// If the user taps/clicks CEDAR, we attempt the current location again
$('#offline-logo-badge').on( 'mousedown', function(){

    location.reload() ;

    if( $(this).hasClass('reloading') ) {
        $(this).removeClass( 'tapped' ) ;
        $(this).removeClass( 'reloading' ) ;
    } else {
        $(this).addClass( 'tapped' ) ;
        $(this).addClass('reloading');
    }

})

/**
 * Check the connection.  If online, show the online message.  Else, show the offline message.
 * The logo will animate to feedback an attempt to connect, and change colour when connected.
 */
function checkConnection() {
    // If offline, flip the logo every few seconds
    var badge = $('#offline-logo-badge') ;
    var offlineMsg = $( '#message-offline' ) ;
    var onlineMsg = $( '#message-online' ) ;

    var slideOptions = {
        duration: 1000 ,
        easing: 'easeOutCubic'
    } ;

    if( navigator.onLine ) {
        badge.addClass( 'online' ) ;
        onlineMsg.slideDown( slideOptions ) ;
        offlineMsg.slideUp( slideOptions ) ;

    } else {
        badge.removeClass( 'online' ) ;
        badge.addClass( 'check' ) ;

        offlineMsg.slideDown( slideOptions ) ;
        onlineMsg.slideUp( slideOptions ) ;

        setTimeout( function(){
            flipOfflineLogo() ;
        }, 500 ) ;
    }
}

/**
 * Spin the logo when attempting a connection. Spin it back pretty soon after
 * to indicate a block in connection.
 */
function flipOfflineLogo() {
    var logo = $('#offline-logo') ;
    var badge = $('#offline-logo-badge') ;

    logo.addClass( 'flip' ) ;

    setTimeout(function(){
        badge.removeClass( 'check' ) ;
    },500);

    setTimeout(function(){
        logo.removeClass( 'flip' ) ;
    },1000);
}

/**
 * populateOfflineLinks
 */
function populateOfflineLinks() {
    if( !caches ){
        return ;
    }

    for( var item in offlineLocations ) {
        var offlineLocation = offlineLocations[ item ] ;

        // Iterate over the offline locations url collection
        // and check for presence in the cache
        searchCache( offlineLocation )
            .then( provideLink )
            .catch( err => err )
             ;
    }
}

/**
 * searchCache accepts a location object and matches on the first URL in its urls collection.
 * On matching, the cached resource will be added to the location as a 'resource' property value
 * and returned.
 * @param location
 * @returns {Promise<any>}
 */
function searchCache( location ){
    return new Promise( (resolve, reject)=>{
        for( var i = 0; i < location.urls.length; i++ ) {
            caches.match( location.urls[ i ] )
                .then( res => {
                    location.resource = res ;
                    resolve( location ) ;
                }) ;
            return ;
        }
        reject( new Error( 'No URLs matching ' + location.label ) ) ;
    }) ;
}

/**
 * provideLink accepts a location object, generating a link from the resources full URL
 * and using the label from the location.label property. The link is added to the cached pages list.
 * @param location
 * @returns {Promise<any>}
 */
function provideLink( location ) {
    return new Promise( (resolve)=>{
        if( location.resource ) {

            // Generate link ID
            var id = linksBox.find( 'li').length ;

            $( '#offline-pages-intro' ).parent().parent().fadeIn() ;

            var liStyle = 'display:none' ;
            var liScript = '$("#linkScript_' + id + '").parent().fadeIn() ;' ;

            var li = '<li style="' + liStyle + '">'
                + '<a class="action" href="' + location.resource.url + '">'
                + location.label + '</a>'
                + '<script id="linkScript_' + id + '">' + liScript + '</script>'
                + '</li>' ;

            linksBox.append(li);
            resolve(location);
        }
    }) ;
}