    
/* ======================================================= 
 *
 *      Auto Photo Albums
 *      Version: 2.1
 *      By castlecode
 *
 *      Contact: http://codecanyon.net/user/castlecode
 *      Created: December 01, 2018
 *
 *      Copyright (c) 2018, castlecode. All rights reserved.
 *      Available only in http://codecanyon.net/
 *      
 *      ---------------------------------
 *      CONTENTS
 *      ---------------------------------
 *
 *      [A] AUTO PHOTO ALBUMS CLASS
 *      [B] DEFAULTS
 *      [C] INIT
 *          [1] SETUP
 *          [2] GO TO DIRECTORY
 *          [3] ORDER THE JSON DATA
 *          [4] TEMPLATE
 *          [5] MAKE BOXES
 *          [6] CLICK ON AN ALBUM
 *          [7] BREADCRUMB
 *          [8] SEARCH
 *          [9] HANDY STUFF
 *          [10] DEEPLINKING
 *      [H] AUTO PHOTO ALBUMS PLUGIN
 *      
 * ======================================================= */

(function( window, $, undefined ){

/* ====================================================================== *
        [A] AUTO PHOTO ALBUMS CLASS
 * ====================================================================== */    

    var AutoPhotoAlbums = function(container, options){
        this.init(container, options);
    }

/* ====================================================================== *
        [B] DEFAULTS
 * ====================================================================== */    
    
    AutoPhotoAlbums.DEFAULTS = {

        directory           : 'galleries/gallery',
        ignoreAlbums        : [],
        configFile          : 'config.txt',

        nameDivider         : '-', // In the name, everything before this characters will not be shown
        linkTarget          : 'new_window', // 'new_window' or 'self'
        limit               : false,
        breadcrumb          : true,
        breadcrumbHome      : 'Home',
        deeplinkingOnAlbums : true,
        scrollTop           : true,
        scrollTopSpeed      : 200,

        /* Thumbnails options */

        thumbnailsOrder     : 'byName', // byDate, byDateReverse, byName, byNameReverse, random
        albumsFirst         : true,
        globalAlbumRatio    : '200x200',
        globalThumbRatio    : false,

        /* search options */

        search              : true,
        searchWord          : 'search',
        
        /* Template options */

        albumTemplate        :  ' <div class="media-box-image"> '+
                                    ' <div data-thumbnail="{{album_cover}}" {{ratio}} data-title="{{name}}" data-alt="{{name}}"></div> '+

                                    ' <div class="media-box-album"> '+
                                        ' <div class="media-box-album-name">{{name}}</div> '+
                                        ' <div class="media-box-album-count"> '+
                                            ' {{image_count}} images <span hide_if_empty="{{album_count}}">and {{album_count}} album(s)</span> '+ 
                                        ' </div> '+ 
                                    ' </div> '+
                                ' </div> ',

        itemTemplate        :   ' <div class="media-box-image mb-open-popup" {{link}} data-src="{{popup_src}}" data-title="{{name}}" data-type="{{popup_type}}"> '+
                                    ' <div data-thumbnail="{{thumb_src}}" {{ratio}} data-title="{{name}}" data-alt="{{name}}"></div> '+
                                    
                                    ' <div class="thumbnail-overlay"> '+

                                        ' <div class="thumbnail-overlay-animated" data-from="top"> '+
                                            ' <div class="thumbnail-overlay-title">{{name}}</div> '+
                                        ' </div> '+

                                    ' </div> '+
                                ' </div>',

        /* Media Boxes options */

        grid                    : {
                boxesToLoadStart                : 9,
                boxesToLoad                     : 9,
                minBoxesPerFilter               : 0,
                lazyLoad                        : true,
                horizontalSpaceBetweenBoxes     : 30,
                verticalSpaceBetweenBoxes       : 30,
                columnWidth                     : 'auto',
                columns                         : 3,
                resolutions                     :   [
                                                        {
                                                            maxWidth: 960,
                                                            columnWidth: 'auto',
                                                            columns: 3,
                                                        },
                                                        {
                                                            maxWidth: 650,
                                                            columnWidth: 'auto',
                                                            columns: 2,
                                                            horizontalSpaceBetweenBoxes: 10,
                                                            verticalSpaceBetweenBoxes: 10,
                                                        },
                                                        {
                                                            maxWidth: 450,
                                                            columnWidth: 'auto',
                                                            columns: 1,
                                                            horizontalSpaceBetweenBoxes: 10,
                                                            verticalSpaceBetweenBoxes: 10,
                                                        },
                                                    ],
                multipleFilterLogic             : 'AND',
                waitUntilThumbWithRatioLoads    : true, // When they have dimensions specified
                waitForAllThumbsNoMatterWhat    : false, // Wait for all the thumbnails to load even if they got dimensions specified
                thumbnailOverlay                : true, //Show the overlay on mouse over
                overlayEffect                   : 'fade', // 'push-up', 'push-down', 'push-up-100%', 'push-down-100%', 'reveal-top', 'reveal-bottom', 'reveal-top-100%', 'reveal-bottom-100%', 'direction-aware', 'direction-aware-fade', 'direction-right', 'direction-left', 'direction-top', 'direction-bottom', 'fade'
                overlaySpeed                    : 200,
                overlayEasing                   : 'default',
                showOnlyVisibleBoxesInPopup     : false,
                considerFilteringInPopup        : true,
                deepLinkingOnPopup              : false,
                deepLinkingOnFilter             : false,
                deepLinkingOnSearch             : false,
                LoadingWord                     : 'Loading...',
                loadMoreWord                    : 'Load More',
                noMoreEntriesWord               : 'No More Entries',
                percentage                      : false,

                popup                           : 'fancybox', // fancybox, magnificpopup, none
                magnificpopup                   :   {
                                                        gallery: true,
                                                        alignTop: false,
                                                        preload: [0,2],    
                                                    },
                fancybox                        :   {
                                                        loop                : false, // Enable infinite gallery navigation 
                                                        margin              : [44, 0], // Space around image, ignored if zoomed-in or viewport smaller than 800px
                                                        keyboard            : true, // Enable keyboard navigation
                                                        arrows              : true, // Should display navigation arrows at the screen edges
                                                        infobar             : false, // Should display infobar (counter and arrows at the top)
                                                        toolbar             : true, // Should display toolbar (buttons at the top)
                                                        buttons             :   [ // What buttons should appear in the top right corner.
                                                                                    'slideShow',
                                                                                    'fullScreen',
                                                                                    'thumbs',
                                                                                    'close'
                                                                                ],
                                                        idleTime            : 3, // Detect "idle" time in seconds
                                                        protect             : false, // Disable right-click and use simple image protection for images
                                                        animationEffect     : 'zoom', // Open/close animation type, it could be: false, 'zoom', 'fade', 'zoom-in-out'
                                                        animationDuration   : 330, // Duration in ms for open/close animation
                                                        transitionEffect    : 'fade', // ransition effect between slides, it could be: false, 'fade', 'slide', 'circular', 'tube', 'zoom-in-out', 'rotate'
                                                        transitionDuration  : 330, // Duration in ms for transition animation
                                                        slideShow           : { autoStart : false, speed : 4000 }, // slideshow settings
                                                        fullScreen          : { autoStart : false, }, // activate or deactivate fullscreen when open
                                                        thumbs              : { autoStart : false, hideOnClose : true },    // Display thumbnails on opening/closing
                                                        touch               : { vertical : true, momentum : true }, // Allow to drag content
                                                        compensateScrollbar : '.fancybox-compensate-for-scrollbar',
                                                    },                                
        },

        phpfile             : 'auto_photo_albums.php',
        directoryURL        : '', // the directoryURL is used for the <img src="" /> so it could be different from directory, if you set directory to an absolute path of your server. 
                                  // i.e. webpage = http://localhost:8888/auto_grid | $directory = /Applications/MAMP/htdocs/auto_grid/galleries/gallery | $directory_url = '/auto_grid/galleries/gallery'
    };    

    /*
        phpfile         => by default it should be in the same directory as your html page, but it can also be a URL for example: http://www.misite.com/auto_photo_albums.php (in that case the directory must be relative to this location, or use absolute path)
        directory       => by default it should be relative to your auto_photo_albums.php file, but you can set it to an absolute path (in that case you need to set the directoryURL)   
        directoryURL    => the directoryURL is used for the <img src="" /> so it could be different from directory, if you set directory to an absolute path of your server

        i.e. if your webpage is: http://localhost:8888/auto_grid 
        phpfile         => http://localhost:8888/auto_grid/auto_photo_albums.php
        directory       => /Applications/MAMP/htdocs/auto_grid/galleries/gallery
        directory_url   => 'http://localhost:8888/auto_grid/galleries/gallery'
    */

/* ====================================================================== *
        [C] INIT
 * ====================================================================== */    

    AutoPhotoAlbums.prototype.init = function(container, options){   
        
    /* ====================================================================== *
            [1] SETUP
     * ====================================================================== */

        /* SETTINGS */
        var settings                    = $.extend(true, {}, AutoPhotoAlbums.DEFAULTS, options);

        /* VARS */
        var $container                  = $(container);      
        var $container_top              = $('<div class="auto_photo_albums_top"></div>').insertBefore($container);
        var $container_id               = $container.attr('id');
        var $root_directory             = settings.directory;
        var $directory_url              = settings.directoryURL == '' ? settings.directory : settings.directoryURL;
        var $current_directory          = '';
        var $mediaboxes                 = $('<div class="mediaboxes_'+$container_id+'"></div>').appendTo($container);
        var $hashid                     = '('+$container.attr('id')+'|album)=';
        var $ignoreAlbums               = settings.ignoreAlbums;
        var $firstTime                  = true;

        /* Add full directory to ignore_albums setting */
        $ignoreAlbums.forEach(function(row, index){
            $ignoreAlbums[index] = $root_directory+'/'+row;
        });
        
    /* ====================================================================== *
            [2] GO TO DIRECTORY
     * ====================================================================== */       

        function go_to_directory(directory){
            $.post(settings.phpfile, { directory : $root_directory+directory, ignore_albums : $ignoreAlbums, config_file : settings.configFile, directory_url : $directory_url+directory }, function(r){
                var json_data = $.parseJSON(r);

                // Apply new settings if any
                var new_settings = {}
                try {
                    new_settings = $.parseJSON(json_data['settings']);
                } catch (e) {
                    le.log('could not parse the settings in this folder');
                    console.log(json_data['settings']);
                }

                if($.isEmptyObject(new_settings) == false){ // if there are new settings
                    new_settings    = $.extend(true, {}, options, new_settings); // first add the settings when the plugin was initialized
                    settings        = $.extend(true, {}, AutoPhotoAlbums.DEFAULTS, new_settings); // then overwrite those settings with the ones from the settings.txt file
                }else{ // if there are no new settings then go back to default
                    settings = $.extend(true, {}, AutoPhotoAlbums.DEFAULTS, options);
                }
            
                // Make boxes
                make_boxes( order_json_data(json_data['output']) );
            });
        }

        if(settings.deeplinkingOnAlbums){
            $current_directory  = get_value_from_hash($hashid);

            go_to_directory($current_directory);
        }else{
            go_to_directory('');
        }

    /* ====================================================================== *
            [3] ORDER THE JSON DATA
     * ====================================================================== */            

        function order_json_data(json_data){
            var new_json_data = json_data.sort(function(a, b) {
                if(settings.thumbnailsOrder == 'byName')         return a.name.localeCompare(b.name); // Keep in mind that localeCompare() is case insensitive. If you want case sensitive, you can use (string1 > string2) - (string1 < string2)
                if(settings.thumbnailsOrder == 'byNameReverse')  return b.name.localeCompare(a.name);
                if(settings.thumbnailsOrder == 'byDate')         return parseFloat(b.date) - parseFloat(a.date);
                if(settings.thumbnailsOrder == 'byDateReverse')  return parseFloat(a.date) - parseFloat(b.date);
                if(settings.thumbnailsOrder == 'random')         return parseFloat(a.random) - parseFloat(b.random);
            });

            if(settings.albumsFirst){
                var albums = [];
                var images  = [];
                new_json_data.forEach(function(row){
                    if(row.is_directory){
                        albums.push(row);
                    }else{
                        images.push(row);
                    }
                });
                return albums.concat(images);
            }else{
                return new_json_data;
            }
        }
    
    /* ====================================================================== *
            [4] TEMPLATE
     * ====================================================================== */    

        // Use the template and replace the variables with the values

        function convert_template(template, item){
            for (var property in item) {
                if (item.hasOwnProperty(property)) {

                    // variable and new value

                    var variable    = property;
                    var new_value   = item[property];

                    // Check nameDivider and remove everything before that

                    if((variable=='name' || variable=='filter' || variable=='extra_filter')){
                        new_value = fix_name(new_value);
                    }

                    // Check link and add Javascript for redirect
                    
                    if(variable=='link'){
                        if(settings.linkTarget == 'self'){
                            new_value = ' onclick=\'location.href="'+new_value+'"\' ';
                        }else if(settings.linkTarget == 'new_window'){
                            new_value = ' onclick=\'window.open("'+new_value+'", "_blank");\' ';
                        }
                    }

                    // Check ratio

                    if(variable=='ratio'){
                        var split   = new_value.toLowerCase().split('x');
                        new_value   = ' data-width="'+split[0]+'" data-height="'+split[1]+'" ';
                    }

                    // Remove hide_if_empty attribute if found

                    if(new_value != ''){
                        template = template.split('hide_if_empty="{{'+variable+'}}"').join('');
                        template = template.split("hide_if_empty='{{"+variable+"}}'").join('');
                        template = template.split("hide_if_empty=&apos;{{"+variable+"}}&apos;").join('');
                    }

                    // Replace variable with value in template

                    template = template.split('{{'+variable+'}}').join(new_value);
                }
            }

            // Add global ratio

            if(item.is_directory){
                if(settings.globalAlbumRatio != false){
                    var split   = settings.globalAlbumRatio.split('x');
                    template    = template.split('{{ratio}}').join( ' data-width="'+split[0]+'" data-height="'+split[1]+'" ' );
                }    
            }else{
                if(settings.globalThumbRatio != false){
                    var split   = settings.globalThumbRatio.split('x');
                    template    = template.split('{{ratio}}').join( ' data-width="'+split[0]+'" data-height="'+split[1]+'" ' );
                }    
            }

            return template;
        }

    /* ====================================================================== *
            [5] MAKE BOXES
     * ====================================================================== */        

        function make_boxes(json_data){

            // Close fancybox if there was some instance open 
            
            if($.fancyboxMB !== undefined){
                $.fancyboxMB.destroy(); // usually when you are inside an album and with fancybox open, and if you hit the "back button" it will go back to the previous album, but without this it would leave fancybox open
            }

            // Destroy the media boxes, if there were any (when it first loads there aren't any)

            if($mediaboxes.data('isotopeMB') !== undefined){
                $mediaboxes.isotopeMB('destroy');
            }
            $mediaboxes.unbind().removeData();
            $mediaboxes.remove();
            $container.html('');
            $container_top.html('');
            $mediaboxes = $('<div class="mediaboxes_'+$container_id+'" id="'+$container.attr('id')+'"></div>').appendTo($container);

            // Limit the items

            if(settings.limit != false){
                json_data = json_data.slice(0,settings.limit);
            }

            // Iterate through all the images

            var html_boxes  = '';
            $.each(json_data, function(i, row){    
                var html            =  convert_template(row.is_directory ? settings.albumTemplate : settings.itemTemplate, row);
                var directory       = row.is_directory ? 'data-directory="'+ row.name +'"' : '';
                var directory_class = row.is_directory ? 'media-box-is-directory' : '';

                html_boxes  +=  ' <div class="media-box '+directory_class+'" '+directory+'>'+ html +'</div>';
            });

            // Add boxes to the DOM

            $mediaboxes.html(html_boxes);

            // extras at the top 

            make_breadcrumb();
            make_search();

            // Init the media boxes

            var media_boxes_extra_settings  =   {
                                                    filterContainer                 : '',
                                                    search                          : '.auto_photo_albums_search_'+$container_id, // i.e. #search
                                                    searchTarget                    : '.thumbnail-overlay, .media-box-content, .media-box-album',
                                                }

            $mediaboxes.mediaBoxes( $.extend(true, {}, settings.grid, media_boxes_extra_settings) );

            $firstTime = false;
        }

    /* ====================================================================== *
            [6] CLICK ON AN ALBUM
     * ====================================================================== */  

         $container.on('click', '.media-box-is-directory .media-box-container', function(){
            var directory       = $(this).parents('.media-box').attr('data-directory');
            $current_directory  += '/'+directory;

            go_to_directory($current_directory);

            if(settings.deeplinkingOnAlbums){
                set_key_and_value_in_hash($hashid, $current_directory);
            }
         });

     /* ====================================================================== *
            [7] BREADCRUMB
     * ====================================================================== */  

        function make_breadcrumb(){
            var breadcrumb  = $('<ul class="media-boxes-breadcrumb"></ul>').prependTo($container_top);
            var html        = '<li><a data-directory="">'+settings.breadcrumbHome+'</a></li>';
            var prefix      = '/';

            if(!settings.breadcrumb){
                breadcrumb.hide();
            }
            
            $current_directory.split('/').forEach(function(row, index){
                if(row != ''){
                    html    += '<li><a data-directory="'+prefix+row+'">'+( fix_name(row) )+'</a></li>'
                    prefix  += row+'/'
                }
            });
            
            breadcrumb.html(html);

            breadcrumb.find('li:last').find('a').addClass('last-breadcrumb'); // add last-breadcrumb class to last breadcrumb

            // Scroll to breadcrumb if the breadcrumb is not visible (usually when the user has scrolled down much and it opens a new album, it needs to go back to top)

            if(settings.scrollTop && !$firstTime){
                if(breadcrumb.visible(true) === false){
                    $('html, body').animate({
                        scrollTop: breadcrumb.offset().top - 80
                    }, settings.scrollTopSpeed);
                }
            }
        }

        $container_top.on('click', '.media-boxes-breadcrumb li a', function(e){
            e.preventDefault();

            var $this           = $(this);

            if($this.hasClass('last-breadcrumb')) return;

            var directory       = $this.attr('data-directory');
            $current_directory  = directory;

            go_to_directory($current_directory);

            if(settings.deeplinkingOnAlbums){
                if($current_directory == ''){
                    remove_from_hash($hashid);
                }else{
                    set_key_and_value_in_hash($hashid, $current_directory);
                }
            }
        });

    /* ====================================================================== *
            [8] SEARCH
     * ====================================================================== */            

        function make_search(){
            if(settings.search){
                html_search     =   ' <div class="media-boxes-search" style="float:right;">'+
                                        ' <span class="media-boxes-icon fa fa-search"></span> '+
                                        ' <input class="auto_photo_albums_search_'+$container_id+'" type="text" id="search" placeholder="'+settings.searchWord+'"> '+
                                        ' <span class="media-boxes-clear fa fa-close"></span> '+
                                    ' </div> ';
                
                $(html_search).prependTo($container_top);                                
            }
        }

    /* ====================================================================== *
            [9] HANDY STUFF
     * ====================================================================== */  

        function fix_name(name){
            if(name.indexOf(settings.nameDivider) >= 0){
                name = name.split(settings.nameDivider)[1];
            }

            return name;
        }

    /* ====================================================================== *
            [10] DEEPLINKING
     * ====================================================================== */  

        var old_hash = get_value_from_hash($hashid);
        function hashchange(){
            var new_hash = get_value_from_hash($hashid);

            if(old_hash != new_hash){ // do this only if the hash of the auto albums changed, if the hash changed for other reason then ignore
                if($container.hasClass('changing-hash') === false){ // if the hash changed by the auto albums (i.e. when you click on an album or breadcrumb) then ignore
                    $current_directory  = get_value_from_hash($hashid);
                    go_to_directory($current_directory); // this is mainly when somebody hits the back button of the browser and the hash change
                }
            }

            old_hash = new_hash;
            $container.removeClass('changing-hash');
        }

        
        $(window).on("hashchange", function (){ // only go if it wasn't a change by a click, if it was done by a back button!
            hashchange();
        });

        function set_hash(new_hash){
            $container.addClass('changing-hash');

            if(new_hash === '' || new_hash === '#' || new_hash === '!'){ // Remove hash
                
                if(history.pushState) { 
                    history.pushState(null, null, ' ');
                    hashchange(); // because pushState doesn't fire the "hashchange" event
                }else{ 
                    location.hash = '#!'; 
                }

            }else{
                location.hash = '#' + new_hash;
            }
        }

        function replace_in_hash(old_value, new_value){
            var hash        = get_hash();

            if(hash.indexOf(old_value) > -1 && old_value != ""){ // if the old value exists, then just replace it
                set_hash( hash.split(old_value).join(new_value) );
            }else{ // if the old value doesn't exists then just add the new one
                set_hash( hash+new_value );
            }
        }

        function get_hash(){
            if(location.href.indexOf("#") != -1){
                //return decodeURI( location.href.split("#")[1] ); // this wouldn't work if there are more # in the hash
                return decodeURI( location.href.substring(location.href.indexOf('#')+1) );
            }else{
                return '';
            }
        }

        function get_value_and_key_from_hash(start){
            var hash            = get_hash();
            var output          = '';
            var index_start     = hash.indexOf(start);
            
            if(index_start > -1 && hash.indexOf(';', index_start) > -1){
                output = hash.substring(index_start, hash.indexOf(';', index_start)+1);
            }

            return output;
        }

        function get_value_from_hash(start){
            var hash            = get_hash();
            var output          = '';
            var index_start     = hash.indexOf(start);
            
            if(index_start > -1 && hash.indexOf(';', index_start) > -1){
                output = hash.substring(index_start+(start.length), hash.indexOf(';', index_start))
            }

            return output;
        }

        function remove_from_hash(start){
            var new_hash    = get_hash().split( get_value_and_key_from_hash(start) ).join('');
            set_hash(new_hash);
        }

        function set_key_and_value_in_hash(start, value){
            if(get_value_from_hash(start) == value){
                // do nothing, since there's no change in the hash
            }else{
                var old_value   = get_value_and_key_from_hash(start);
                var new_value   = start + value + ';'; // i.e. // (grid|popup)=some_image.png;
                replace_in_hash(old_value, new_value);
            }
        }
        
    };//END OF INIT   

/* ====================================================================== *
        [H] AUTO PHOTO ALBUMS PLUGIN
 * ====================================================================== */

    $.fn.autoPhotoAlbums = function(options, content, callback) {

        return this.each(function(key, value){
            var $this   = $(this);
            var data    = $this.data('autoPhotoAlbums')
            
            // Initialize plugin
            if (!data && typeof options != 'string'){
                $this.data('autoPhotoAlbums', new AutoPhotoAlbums(this, options));
            }

            // Call method
            if (data && typeof options == 'string'){
                data[options](content, callback);    
            }
        });

    };      
    
})( window, jQuery );