;(function ($, window, document, undefined) {

'use strict';

Tennpipes.libs.dropdown = {
  name : 'dropdown',

  version : '5.5.1',

  settings : {
    active_class : 'open',
    disabled_class : 'disabled',
    mega_class : 'mega',
    align : 'bottom',
    is_hover : false,
    hover_timeout : 150,
    opened : function () {},
    closed : function () {}
  },

  init : function (scope, method, options) {
    Tennpipes.inherit(this, 'throttle');

    $.extend(true, this.settings, method, options);
    this.bindings(method, options);
  },

  events : function (scope) {
    var self = this,
        S = self.S;

    S(this.scope)
      .off('.dropdown')
      .on('click.fndtn.dropdown', '[' + this.attr_name() + ']', function (e) {
        var settings = S(this).data(self.attr_name(true) + '-init') || self.settings;
        if (!settings.is_hover || Modernizr.touch) {
          e.preventDefault();
          if (S(this).parent('[data-reveal-id]')) {
            e.stopPropagation();
          }
          self.toggle($(this));
        }
      })
      .on('mouseenter.fndtn.dropdown', '[' + this.attr_name() + '], [' + this.attr_name() + '-content]', function (e) {
        var $this = S(this),
            dropdown,
            target;

        clearTimeout(self.timeout);

        if ($this.data(self.data_attr())) {
          dropdown = S('#' + $this.data(self.data_attr()));
          target = $this;
        } else {
          dropdown = $this;
          target = S('[' + self.attr_name() + '="' + dropdown.attr('id') + '"]');
        }

        var settings = target.data(self.attr_name(true) + '-init') || self.settings;

        if (S(e.currentTarget).data(self.data_attr()) && settings.is_hover) {
          self.closeall.call(self);
        }

        if (settings.is_hover) {
          self.open.apply(self, [dropdown, target]);
        }
      })
      .on('mouseleave.fndtn.dropdown', '[' + this.attr_name() + '], [' + this.attr_name() + '-content]', function (e) {
        var $this = S(this);
        var settings;

        if ($this.data(self.data_attr())) {
            settings = $this.data(self.data_attr(true) + '-init') || self.settings;
        } else {
            var target   = S('[' + self.attr_name() + '="' + S(this).attr('id') + '"]'),
                settings = target.data(self.attr_name(true) + '-init') || self.settings;
        }

        self.timeout = setTimeout(function () {
          if ($this.data(self.data_attr())) {
            if (settings.is_hover) {
              self.close.call(self, S('#' + $this.data(self.data_attr())));
            }
          } else {
            if (settings.is_hover) {
              self.close.call(self, $this);
            }
          }
        }.bind(this), settings.hover_timeout);
      })
      .on('click.fndtn.dropdown', function (e) {
        var parent = S(e.target).closest('[' + self.attr_name() + '-content]');
        var links  = parent.find('a');

        if (links.length > 0 && parent.attr('aria-autoclose') !== 'false') {
            self.close.call(self, S('[' + self.attr_name() + '-content]'));
        }

        if (e.target !== document && !$.contains(document.documentElement, e.target)) {
          return;
        }

        if (S(e.target).closest('[' + self.attr_name() + ']').length > 0) {
          return;
        }

        if (!(S(e.target).data('revealId')) &&
          (parent.length > 0 && (S(e.target).is('[' + self.attr_name() + '-content]') ||
            $.contains(parent.first()[0], e.target)))) {
          e.stopPropagation();
          return;
        }

        self.close.call(self, S('[' + self.attr_name() + '-content]'));
      })
      .on('opened.fndtn.dropdown', '[' + self.attr_name() + '-content]', function () {
        self.settings.opened.call(this);
      })
      .on('closed.fndtn.dropdown', '[' + self.attr_name() + '-content]', function () {
        self.settings.closed.call(this);
      });

    S(window)
      .off('.dropdown')
      .on('resize.fndtn.dropdown', self.throttle(function () {
        self.resize.call(self);
      }, 50));

    this.resize();
  },

  close : function (dropdown) {
    var self = this;
    dropdown.each(function () {
      var original_target = $('[' + self.attr_name() + '=' + dropdown[0].id + ']') || $('aria-controls=' + dropdown[0].id + ']');
      original_target.attr('aria-expanded', 'false');
      if (self.S(this).hasClass(self.settings.active_class)) {
        self.S(this)
          .css(Tennpipes.rtl ? 'right' : 'left', '-99999px')
          .attr('aria-hidden', 'true')
          .removeClass(self.settings.active_class)
          .prev('[' + self.attr_name() + ']')
          .removeClass(self.settings.active_class)
          .removeData('target');

        self.S(this).trigger('closed').trigger('closed.fndtn.dropdown', [dropdown]);
      }
    });
    dropdown.removeClass('f-open-' + this.attr_name(true));
  },

  closeall : function () {
    var self = this;
    $.each(self.S('.f-open-' + this.attr_name(true)), function () {
      self.close.call(self, self.S(this));
    });
  },

  open : function (dropdown, target) {
    this
      .css(dropdown
      .addClass(this.settings.active_class), target);
    dropdown.prev('[' + this.attr_name() + ']').addClass(this.settings.active_class);
    dropdown.data('target', target.get(0)).trigger('opened').trigger('opened.fndtn.dropdown', [dropdown, target]);
    dropdown.attr('aria-hidden', 'false');
    target.attr('aria-expanded', 'true');
    dropdown.focus();
    dropdown.addClass('f-open-' + this.attr_name(true));
  },

  data_attr : function () {
    if (this.namespace.length > 0) {
      return this.namespace + '-' + this.name;
    }

    return this.name;
  },

  toggle : function (target) {
    if (target.hasClass(this.settings.disabled_class)) {
      return;
    }
    var dropdown = this.S('#' + target.data(this.data_attr()));
    if (dropdown.length === 0) {
      // No dropdown found, not continuing
      return;
    }

    this.close.call(this, this.S('[' + this.attr_name() + '-content]').not(dropdown));

    if (dropdown.hasClass(this.settings.active_class)) {
      this.close.call(this, dropdown);
      if (dropdown.data('target') !== target.get(0)) {
        this.open.call(this, dropdown, target);
      }
    } else {
      this.open.call(this, dropdown, target);
    }
  },

  resize : function () {
    var dropdown = this.S('[' + this.attr_name() + '-content].open');
    var target = $(dropdown.data("target"));

    if (dropdown.length && target.length) {
      this.css(dropdown, target);
    }
  },

  css : function (dropdown, target) {
    var left_offset = Math.max((target.width() - dropdown.width()) / 2, 8),
        settings = target.data(this.attr_name(true) + '-init') || this.settings;

    this.clear_idx();

    if (this.small()) {
      var p = this.dirs.bottom.call(dropdown, target, settings);

      dropdown.attr('style', '').removeClass('drop-left drop-right drop-top').css({
        position : 'absolute',
        width : '95%',
        'max-width' : 'none',
        top : p.top
      });

      dropdown.css(Tennpipes.rtl ? 'right' : 'left', left_offset);
    } else {

      this.style(dropdown, target, settings);
    }

    return dropdown;
  },

  style : function (dropdown, target, settings) {
    var css = $.extend({position : 'absolute'},
      this.dirs[settings.align].call(dropdown, target, settings));

    dropdown.attr('style', '').css(css);
  },

  // return CSS property object
  // `this` is the dropdown
  dirs : {
    // Calculate target offset
    _base : function (t) {
      var o_p = this.offsetParent(),
          o = o_p.offset(),
          p = t.offset();

      p.top -= o.top;
      p.left -= o.left;

      //set some flags on the p object to pass along
      p.missRight = false;
      p.missTop = false;
      p.missLeft = false;
      p.leftRightFlag = false;

      //lets see if the panel will be off the screen
      //get the actual width of the page and store it
      var actualBodyWidth;
      if (document.getElementsByClassName('row')[0]) {
        actualBodyWidth = document.getElementsByClassName('row')[0].clientWidth;
      } else {
        actualBodyWidth = window.outerWidth;
      }

      var actualMarginWidth = (window.outerWidth - actualBodyWidth) / 2;
      var actualBoundary = actualBodyWidth;

      if (!this.hasClass('mega')) {
        //miss top
        if (t.offset().top <= this.outerHeight()) {
          p.missTop = true;
          actualBoundary = window.outerWidth - actualMarginWidth;
          p.leftRightFlag = true;
        }

        //miss right
        if (t.offset().left + this.outerWidth() > t.offset().left + actualMarginWidth && t.offset().left - actualMarginWidth > this.outerWidth()) {
          p.missRight = true;
          p.missLeft = false;
        }

        //miss left
        if (t.offset().left - this.outerWidth() <= 0) {
          p.missLeft = true;
          p.missRight = false;
        }
      }

      return p;
    },

    top : function (t, s) {
      var self = Tennpipes.libs.dropdown,
          p = self.dirs._base.call(this, t);

      this.addClass('drop-top');

      if (p.missTop == true) {
        p.top = p.top + t.outerHeight() + this.outerHeight();
        this.removeClass('drop-top');
      }

      if (p.missRight == true) {
        p.left = p.left - this.outerWidth() + t.outerWidth();
      }

      if (t.outerWidth() < this.outerWidth() || self.small() || this.hasClass(s.mega_menu)) {
        self.adjust_pip(this, t, s, p);
      }

      if (Tennpipes.rtl) {
        return {left : p.left - this.outerWidth() + t.outerWidth(),
          top : p.top - this.outerHeight()};
      }

      return {left : p.left, top : p.top - this.outerHeight()};
    },

    bottom : function (t, s) {
      var self = Tennpipes.libs.dropdown,
          p = self.dirs._base.call(this, t);

      if (p.missRight == true) {
        p.left = p.left - this.outerWidth() + t.outerWidth();
      }

      if (t.outerWidth() < this.outerWidth() || self.small() || this.hasClass(s.mega_menu)) {
        self.adjust_pip(this, t, s, p);
      }

      if (self.rtl) {
        return {left : p.left - this.outerWidth() + t.outerWidth(), top : p.top + t.outerHeight()};
      }

      return {left : p.left, top : p.top + t.outerHeight()};
    },

    left : function (t, s) {
      var p = Tennpipes.libs.dropdown.dirs._base.call(this, t);

      this.addClass('drop-left');

      if (p.missLeft == true) {
        p.left =  p.left + this.outerWidth();
        p.top = p.top + t.outerHeight();
        this.removeClass('drop-left');
      }

      return {left : p.left - this.outerWidth(), top : p.top};
    },

    right : function (t, s) {
      var p = Tennpipes.libs.dropdown.dirs._base.call(this, t);

      this.addClass('drop-right');

      if (p.missRight == true) {
        p.left = p.left - this.outerWidth();
        p.top = p.top + t.outerHeight();
        this.removeClass('drop-right');
      } else {
        p.triggeredRight = true;
      }

      var self = Tennpipes.libs.dropdown;

      if (t.outerWidth() < this.outerWidth() || self.small() || this.hasClass(s.mega_menu)) {
        self.adjust_pip(this, t, s, p);
      }

      return {left : p.left + t.outerWidth(), top : p.top};
    }
  },

  // Insert rule to style psuedo elements
  adjust_pip : function (dropdown, target, settings, position) {
    var sheet = Tennpipes.stylesheet,
        pip_offset_base = 8;

    if (dropdown.hasClass(settings.mega_class)) {
      pip_offset_base = position.left + (target.outerWidth() / 2) - 8;
    } else if (this.small()) {
      pip_offset_base += position.left - 8;
    }

    this.rule_idx = sheet.cssRules.length;

    //default
    var sel_before = '.f-dropdown.open:before',
        sel_after  = '.f-dropdown.open:after',
        css_before = 'left: ' + pip_offset_base + 'px;',
        css_after  = 'left: ' + (pip_offset_base - 1) + 'px;';

    if (position.missRight == true) {
      pip_offset_base = dropdown.outerWidth() - 23;
      sel_before = '.f-dropdown.open:before',
      sel_after  = '.f-dropdown.open:after',
      css_before = 'left: ' + pip_offset_base + 'px;',
      css_after  = 'left: ' + (pip_offset_base - 1) + 'px;';
    }

    //just a case where right is fired, but its not missing right
    if (position.triggeredRight == true) {
      sel_before = '.f-dropdown.open:before',
      sel_after  = '.f-dropdown.open:after',
      css_before = 'left:-12px;',
      css_after  = 'left:-14px;';
    }

    if (sheet.insertRule) {
      sheet.insertRule([sel_before, '{', css_before, '}'].join(' '), this.rule_idx);
      sheet.insertRule([sel_after, '{', css_after, '}'].join(' '), this.rule_idx + 1);
    } else {
      sheet.addRule(sel_before, css_before, this.rule_idx);
      sheet.addRule(sel_after, css_after, this.rule_idx + 1);
    }
  },

  // Remove old dropdown rule index
  clear_idx : function () {
    var sheet = Tennpipes.stylesheet;

    if (typeof this.rule_idx !== 'undefined') {
      sheet.deleteRule(this.rule_idx);
      sheet.deleteRule(this.rule_idx);
      delete this.rule_idx;
    }
  },

  small : function () {
    return matchMedia(Tennpipes.media_queries.small).matches &&
      !matchMedia(Tennpipes.media_queries.medium).matches;
  },

  off : function () {
    this.S(this.scope).off('.fndtn.dropdown');
    this.S('html, body').off('.fndtn.dropdown');
    this.S(window).off('.fndtn.dropdown');
    this.S('[data-dropdown-content]').off('.fndtn.dropdown');
  },

  reflow : function () {}
};

}(jQuery, window, window.document));