text: 'use strict';
  
  angular.module('mgcrea.ngStrap.popover', ['mgcrea.ngStrap.tooltip'])
  
    .provider('$popover', function() {
  
      var defaults = this.defaults = {
        animation: 'animation-fade',
        placement: 'right',
        template: 'popover/popover.tpl.html',
        contentTemplate: false,
        trigger: 'click',
        keyboard: true,
        html: false,
        title: '',
        content: '',
        delay: 0,
        container: false
      };
  
      this.$get = function($tooltip) {
  
        function PopoverFactory(element, config) {
  
          // Common vars
          var options = angular.extend({}, defaults, config);
  
          var $popover = $tooltip(element, options);
  
          // Support scope as string options [/*title, */content]
          if(options.content) {
            $popover.$scope.content = options.content;
          }
  
          return $popover;
  
        }
  
        return PopoverFactory;
  
      };
  
    })
  
    .directive('bsPopover', function($window, $location, $sce, $popover) {
  
      var requestAnimationFrame = $window.requestAnimationFrame || $window.setTimeout;
  
      return {
        restrict: 'EAC',
        scope: true,
        link: function postLink(scope, element, attr) {
  
          // Directive options
          var options = {scope: scope};
          angular.forEach(['template', 'contentTemplate', 'placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation'], function(key) {
            if(angular.isDefined(attr[key])) options[key] = attr[key];
          });
  
          // Support scope as data-attrs
          angular.forEach(['title', 'content'], function(key) {
            attr[key] && attr.$observe(key, function(newValue, oldValue) {
              scope[key] = newValue;
              angular.isDefined(oldValue) && requestAnimationFrame(function() {
                popover && popover.$applyPlacement();
              });
            });
          });
  
          // Support scope as an object
          attr.bsPopover && scope.$watch(attr.bsPopover, function(newValue, oldValue) {
            if(angular.isObject(newValue)) {
              angular.extend(scope, newValue);
            } else {
              scope.content = newValue;
            }
            angular.isDefined(oldValue) && requestAnimationFrame(function() {
              popover && popover.$applyPlacement();
            });
          }, true);
  
          // Initialize popover
            var popover = $popover(element, options);
  
            scope.$on('hide.popovers', function(evt, msg){
                if(popover.$isShown){
                    popover.hide();
                }
            });
  
            // If we have defined an id then add custom listeners
            if(attr.id !== undefined){
                scope.$on('show.'+attr.id, function(evt, position){
                    popover.show(position);
                });
                scope.$on('hide.'+attr.id, function(evt, msg){
                    if(popover.$isShown){
                        popover.hide();
                    }
                });
                scope.$on('toggle.'+attr.id, function(evt, position){
                    popover.toggle(position);
                });
            }
  
          // Garbage collection
          scope.$on('$destroy', function() {
            popover.destroy();
            options = null;
            popover = null;
          });
  
        }
      };
  
    });
  