text: angular.module('ui.bootstrap.buttons', [])
  
  .constant('buttonConfig', {
    activeClass: 'active',
    toggleEvent: 'click'
  })
  
  .controller('ButtonsController', ['buttonConfig', function(buttonConfig) {
    this.activeClass = buttonConfig.activeClass || 'active';
    this.toggleEvent = buttonConfig.toggleEvent || 'click';
  }])
  
  .directive('btnRadio', function () {
    return {
      require: ['btnRadio', 'ngModel'],
      controller: 'ButtonsController',
      link: function (scope, element, attrs, ctrls) {
        var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];
  
        //model -> UI
        ngModelCtrl.$render = function () {
          element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, scope.$eval(attrs.btnRadio)));
        };
  
        //ui->model
        element.bind(buttonsCtrl.toggleEvent, function () {
          var isActive = element.hasClass(buttonsCtrl.activeClass);
  
          if (!isActive || angular.isDefined(attrs.uncheckable)) {
            scope.$apply(function () {
              ngModelCtrl.$setViewValue(isActive ? null : scope.$eval(attrs.btnRadio));
              ngModelCtrl.$render();
            });
          }
        });
      }
    };
  })
  
  .directive('btnCheckbox', function () {
    return {
      require: ['btnCheckbox', 'ngModel'],
      controller: 'ButtonsController',
      link: function (scope, element, attrs, ctrls) {
        var buttonsCtrl = ctrls[0], ngModelCtrl = ctrls[1];
  
        function getTrueValue() {
          return getCheckboxValue(attrs.btnCheckboxTrue, true);
        }
  
        function getFalseValue() {
          return getCheckboxValue(attrs.btnCheckboxFalse, false);
        }
  
        function getCheckboxValue(attributeValue, defaultValue) {
          var val = scope.$eval(attributeValue);
          return angular.isDefined(val) ? val : defaultValue;
        }
  
        //model -> UI
        ngModelCtrl.$render = function () {
          element.toggleClass(buttonsCtrl.activeClass, angular.equals(ngModelCtrl.$modelValue, getTrueValue()));
        };
  
        //ui->model
        element.bind(buttonsCtrl.toggleEvent, function () {
          scope.$apply(function () {
            ngModelCtrl.$setViewValue(element.hasClass(buttonsCtrl.activeClass) ? getFalseValue() : getTrueValue());
            ngModelCtrl.$render();
          });
        });
      }
    };
  });
  