/*

 * Sidr

 * https://github.com/artberri/sidr

 *

 * Copyright (c) 2013-2016 Alberto Varela

 * Licensed under the MIT license.

 */



;(function( $ ){



  var sidrMoving = false,

      sidrOpened = false;



  // Private methods

  var privateMethods = {

  	// Check for valids urls

    // From : http://stackoverflow.com/questions/5717093/check-if-a-javascript-string-is-an-url

    isUrl: function (str) {

      var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol

            '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|'+ // domain name

            '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address

            '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path

            '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string

            '(\\#[-a-z\\d_]*)?$','i'); // fragment locator



      if (pattern.test(str)) {

        return true;

      } else {

        return false;

      }

    },



    // Loads the content into the menu bar

    loadContent: function($menu, content) {

      $menu.html(content);

    },

    // Add sidr prefixes

    addPrefix: function($element) {

      var elementId = $element.attr('id'),

          elementClass = $element.attr('class');



      if ( $element.hasClass( 'fa' ) ) {

        return;

      }



      if ( $element.hasClass( 'icon' ) ) {

        return;

      }



      if(typeof elementId === 'string' && '' !== elementId) {

        $element.attr('id', elementId.replace(/([A-Za-z0-9_.\-]+)/g, 'sidr-id-$1'));

      }

      if(typeof elementClass === 'string' && '' !== elementClass && 'sidr-inner' !== elementClass) {

        $element.attr('class', elementClass.replace(/([A-Za-z0-9_.\-]+)/g, 'sidr-class-$1'));

      }

      $element.removeAttr('style');

    },

    execute: function(action, name, callback) {

      // Check arguments

      if(typeof name === 'function') {

        callback = name;

        name = 'sidr';

      }

      else if(!name) {

        name = 'sidr';

      }



      // Declaring

      var $menu = $('#' + name),

          $body = $($menu.data('body')),

          $html = $('html'),

          menuWidth = $menu.outerWidth(true),

          speed = $menu.data('speed'),

          side = $menu.data('side'),

          displace = $menu.data('displace'),

          onOpen = $menu.data('onOpen'),

          onClose = $menu.data('onClose'),

          bodyAnimation,

          menuAnimation,

          scrollTop,

          bodyClass = (name === 'sidr' ? 'sidr-open' : 'sidr-open ' + name + '-open');



      // Open Sidr

      if('open' === action || ('toggle' === action && !$menu.is(':visible'))) {

        // Check if we can open it

        if( $menu.is(':visible') || sidrMoving ) {

          return;

        }



        // If another menu opened close first

        if(sidrOpened !== false) {

          methods.close(sidrOpened, function() {

            methods.open(name);

          });



          return;

        }



        // Lock sidr

        sidrMoving = true;



        // Left or right?

        if(side === 'left') {

          bodyAnimation = {left: menuWidth + 'px'};

          menuAnimation = {left: '0px'};

        }

        else {

          bodyAnimation = {right: menuWidth + 'px'};

          menuAnimation = {right: '0px'};

        }



        // Prepare page if container is body

        if($body.is('body')){

          scrollTop = $html.scrollTop();

          $html.css('overflow-x', 'hidden').scrollTop(scrollTop);

        }



        // Open menu

        if(displace){

          $body.addClass('sidr-animating').css({

            width: $body.width(),

            position: 'absolute'

          }).animate(bodyAnimation, speed, function() {

            $(this).addClass(bodyClass);

          });

        }

        else {

          setTimeout(function() {

            $(this).addClass(bodyClass);

          }, speed);

        }

        $menu.css('display', 'block').animate(menuAnimation, speed, function() {

          sidrMoving = false;

          sidrOpened = name;

          // Callback

          if(typeof callback === 'function') {

            callback(name);

          }

          $body.removeClass('sidr-animating');

        });



        // onOpen callback

        onOpen();

      }

      // Close Sidr

      else {

        // Check if we can close it

        if( !$menu.is(':visible') || sidrMoving ) {

          return;

        }



        // Lock sidr

        sidrMoving = true;



        // Right or left menu?

        if(side === 'left') {

          bodyAnimation = {left: 0};

          menuAnimation = {left: '-' + menuWidth + 'px'};

        }

        else {

          bodyAnimation = {right: 0};

          menuAnimation = {right: '-' + menuWidth + 'px'};

        }



        // Close menu

        if($body.is('body')){

          scrollTop = $html.scrollTop();

          $html.removeAttr('style').scrollTop(scrollTop);

        }

        $body.addClass('sidr-animating').animate(bodyAnimation, speed).removeClass(bodyClass);

        $menu.animate(menuAnimation, speed, function() {

          $menu.hide();

          $body.removeAttr('style');

          $('html').removeAttr('style');

          sidrMoving = false;

          sidrOpened = false;

          // Callback

          if(typeof callback === 'function') {

            callback(name);

          }

          $body.removeClass('sidr-animating');

        });



        // onClose callback

        onClose();

      }

    }

  };



  // Sidr public methods

  var methods = {

    open: function(name, callback) {

      privateMethods.execute('open', name, callback);

    },

    close: function(name, callback) {

      privateMethods.execute('close', name, callback);

    },

    toggle: function(name, callback) {

      privateMethods.execute('toggle', name, callback);

    },

    // I made a typo, so I mantain this method to keep backward compatibilty with 1.1.1v and previous

    toogle: function(name, callback) {

      privateMethods.execute('toggle', name, callback);

    }

  };



  $.sidr = function( method ) {



    if ( methods[method] ) {

      return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));

    }

    else if ( typeof method === 'function' || typeof method === 'string' || ! method ) {

      return methods.toggle.apply( this, arguments );

    }

    else {

      $.error( 'Method ' + method + ' does not exist on jQuery.sidr' );

    }



  };



  $.fn.sidr = function( options ) {



    var settings = $.extend( {

      name          : 'sidr',         // Name for the 'sidr'

      speed         : 200,            // Accepts standard jQuery effects speeds (i.e. fast, normal or milliseconds)

      side          : 'left',         // Accepts 'left' or 'right'

      source        : null,           // Override the source of the content.

      renaming      : true,           // The ids and classes will be prepended with a prefix when loading existent content

      body          : 'body',         // Page container selector,

      displace 		: true, 		  // Displace the body content or not

      onOpen        : function() {},  // Callback when sidr opened

      onClose       : function() {}   // Callback when sidr closed

    }, options);



    var name = settings.name,

        $sideMenu = $('#' + name);



    // If the side menu do not exist create it

    if( $sideMenu.length === 0 ) {

      $sideMenu = $('<div />')

        .attr('id', name)

        .appendTo($('body'));

    }



    // Adding styles and options

    $sideMenu

      .addClass('sidr')

      .addClass(settings.side)

      .data({

        speed: settings.speed,

        side: settings.side,

        body: settings.body,

        displace: settings.displace,

        onOpen: settings.onOpen,

        onClose: settings.onClose

      });



    // The menu content

    if(typeof settings.source === 'function') {

      var newContent = settings.source(name);

      privateMethods.loadContent($sideMenu, newContent);

    }

    else if(typeof settings.source === 'string' && privateMethods.isUrl(settings.source)) {

      $.get(settings.source, function(data) {

        privateMethods.loadContent($sideMenu, data);

      });

    }

    else if(typeof settings.source === 'string') {

      var htmlContent = '',

          selectors = settings.source.split(',');



      $.each(selectors, function(index, element) {

        htmlContent += '<div class="sidr-inner">' + $(element).html() + '</div>';

      });



      // Renaming ids and classes

      if(settings.renaming) {

        var $htmlContent = $('<div />').html(htmlContent);

        $htmlContent.find('*').each(function(index, element) {

          var $element = $(element);

          privateMethods.addPrefix($element);

        });

        htmlContent = $htmlContent.html();

      }

      privateMethods.loadContent($sideMenu, htmlContent);

    }

    else if(settings.source !== null) {

      $.error('Invalid Sidr Source');

    }



    return this.each(function(){

      var $this = $(this),

          data = $this.data('sidr');



      // If the plugin hasn't been initialized yet

      if ( ! data ) {



          $this.on('click',function(e) {

            methods.toggle(name);

            return false;

          });

          

      }

    });

  };



})( jQuery );