define(['ui/component', 'handlebars', 'lib/handlebars/helpers'], function (componentFactory, Handlebars, Helpers0) { 'use strict';

    componentFactory = componentFactory && Object.prototype.hasOwnProperty.call(componentFactory, 'default') ? componentFactory['default'] : componentFactory;
    Handlebars = Handlebars && Object.prototype.hasOwnProperty.call(Handlebars, 'default') ? Handlebars['default'] : Handlebars;
    Helpers0 = Helpers0 && Object.prototype.hasOwnProperty.call(Helpers0, 'default') ? Helpers0['default'] : Helpers0;

    if (!Helpers0.__initialized) {
      Helpers0(Handlebars);
      Helpers0.__initialized = true;
    }
    var Template = Handlebars.template(function (Handlebars,depth0,helpers,partials,data) {
      this.compilerInfo = [4,'>= 1.0.0'];
    helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
      var buffer = "", stack1, helper, functionType="function", escapeExpression=this.escapeExpression, self=this;

    function program1(depth0,data) {
      
      var buffer = "", stack1, helper;
      buffer += "btn-";
      if (helper = helpers.type) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.type); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1);
      return buffer;
      }

    function program3(depth0,data) {
      
      
      return " small";
      }

    function program5(depth0,data) {
      
      var buffer = "", stack1, helper;
      buffer += " ";
      if (helper = helpers.cls) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.cls); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1);
      return buffer;
      }

    function program7(depth0,data) {
      
      var buffer = "", stack1, helper;
      buffer += " title=\"";
      if (helper = helpers.title) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.title); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "\"";
      return buffer;
      }

    function program9(depth0,data) {
      
      var buffer = "", stack1, helper;
      buffer += "<span class=\"icon icon-";
      if (helper = helpers.icon) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.icon); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "\"></span>";
      return buffer;
      }

      buffer += "<button class=\"";
      stack1 = helpers['if'].call(depth0, (depth0 && depth0.type), {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
      if(stack1 || stack1 === 0) { buffer += stack1; }
      stack1 = helpers['if'].call(depth0, (depth0 && depth0.small), {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
      if(stack1 || stack1 === 0) { buffer += stack1; }
      stack1 = helpers['if'].call(depth0, (depth0 && depth0.cls), {hash:{},inverse:self.noop,fn:self.program(5, program5, data),data:data});
      if(stack1 || stack1 === 0) { buffer += stack1; }
      buffer += "\" data-control=\"";
      if (helper = helpers.id) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.id); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "\"";
      stack1 = helpers['if'].call(depth0, (depth0 && depth0.title), {hash:{},inverse:self.noop,fn:self.program(7, program7, data),data:data});
      if(stack1 || stack1 === 0) { buffer += stack1; }
      buffer += ">\n    ";
      stack1 = helpers['if'].call(depth0, (depth0 && depth0.icon), {hash:{},inverse:self.noop,fn:self.program(9, program9, data),data:data});
      if(stack1 || stack1 === 0) { buffer += stack1; }
      buffer += "\n    <span class=\"label\">";
      if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "</span>\n</button>\n";
      return buffer;
      });
    function buttonTpl(data, options, asString) {
      var html = Template(data, options);
      return (asString || true) ? html : $(html);
    }

    /**
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * as published by the Free Software Foundation; under version 2
     * of the License (non-upgradable).
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software
     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
     *
     * Copyright (c) 2017 (original work) Open Assessment Technologies SA ;
     */

    /**
     * Some default config
     * @type {Object}
     */
    const defaults = {
      small: true
    };

    /**
     * @typedef {Object} buttonConfig Defines the config entries available to setup a button
     * @property {String} id - The identifier of the button
     * @property {String} label - The caption of the button
     * @property {String} [title] - An optional tooltip for the button
     * @property {String} [icon] - An optional icon for the button
     * @property {String} [type] - The type of button to build
     * @property {Boolean} [small] - Whether build a small button (default: true)
     * @property {String} [cls] - An additional CSS class name
     */

    /**
     * Builds a simple button component.
     *
     * @example
     *  // button with simple action
     *  const button = buttonFactory({
     *      id: 'foo',
     *      label: 'Foo',
     *      title: 'Foo Bar',
     *      icon: 'globe',
     *      type: 'info'
     *  })
     *      .on('click', function() {
     *          // do something
     *      })
     *      .render(container);
     *
     *  // button with handling of async action
     *  const button = buttonFactory({
     *      id: 'foo',
     *      label: 'Foo',
     *      title: 'Foo Bar',
     *      icon: 'globe',
     *      type: 'info'
     *  })
     *      .before('click', function(){
     *          this.disable();
     *      })
     *      .on('click', function() {
     *          return new Promise(resolve => {
     *              // do something
     *              resolve();
     *          });
     *      })
     *      .after('click', function(){
     *          this.enable();
     *      })
     *      .render(container);
     *
     * @param {buttonConfig} config
     * @param {String} config.id - The identifier of the button
     * @param {String} config.label - The caption of the button
     * @param {String} [config.title] - An optional tooltip for the button
     * @param {String} [config.icon] - An optional icon for the button
     * @param {String} [config.type] - The type of button to build
     * @param {Boolean} [config.small] - Whether build a small button (default: true)
     * @param {String} [config.cls] - An additional CSS class name
     * @returns {button}
     * @fires click - When the button is clicked
     * @fires ready - When the button is ready to work
     */
    function buttonFactory(config) {
      return componentFactory({
        /**
         * Gets the identifier of the button
         * @returns {String}
         */
        getId() {
          return this.getConfig().id;
        }
      }, defaults).setTemplate(buttonTpl)

      // renders the component
      .on('render', function onButtonRender() {
        this.getElement().on('click', e => {
          e.preventDefault();

          /**
           * @event click
           * @param {String} buttonId
           */
          this.trigger('click', this.getId());
        });

        /**
         * @event ready
         */
        this.trigger('ready');
      })

      // take care of the disable state
      .on('disable', function onButtonDisable() {
        this.getElement().prop('disabled', true);
      }).on('enable', function onButtonEnable() {
        this.getElement().prop('disabled', false);
      }).init(config);
    }

    return buttonFactory;

});
