define(['lodash', 'i18n', 'ui/component', 'ui/generis/validator/validator', 'handlebars', 'lib/handlebars/helpers', 'css!ui/generis/widget/css/widget.css'], function (_, __, componentFactory, generisValidatorFactory, Handlebars, Helpers0, widget_css) { 'use strict';

    _ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _;
    __ = __ && Object.prototype.hasOwnProperty.call(__, 'default') ? __['default'] : __;
    componentFactory = componentFactory && Object.prototype.hasOwnProperty.call(componentFactory, 'default') ? componentFactory['default'] : componentFactory;
    generisValidatorFactory = generisValidatorFactory && Object.prototype.hasOwnProperty.call(generisValidatorFactory, 'default') ? generisValidatorFactory['default'] : generisValidatorFactory;
    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, helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, functionType="function", self=this;

    function program1(depth0,data) {
      
      var buffer = "", helper, options;
      buffer += "\n    <abbr title=\""
        + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "This field is required", options) : helperMissing.call(depth0, "__", "This field is required", options)))
        + "\">*</abbr>\n    ";
      return buffer;
      }

      buffer += "<label for=\"";
      if (helper = helpers.uri) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.uri); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "\">\n    ";
      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)
        + "\n    ";
      stack1 = helpers['if'].call(depth0, (depth0 && depth0.required), {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
      if(stack1 || stack1 === 0) { buffer += stack1; }
      buffer += "\n</label>";
      return buffer;
      });
    function ptl(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;
     */
    Handlebars.registerPartial('ui-generis-widget-label', ptl);
    /**
     * The factory
     * @param {Object} [options.validator]
     * @param {Object} [spec]
     * @returns {ui/component}
     * @deprecated replaced by `ui/form/widget/widget`
     */
    function factory(options, spec) {
      var widget;
      options = options || {};
      widget = componentFactory(_.assign({
        /**
         * Gets widget value
         * @returns {String}
         */
        get: function get() {
          var ret = this.config.value || '';
          if (this.is('rendered')) {
            ret = this.getElement().find('[name="' + this.config.uri + '"]').val();
          }
          return ret;
        },
        /**
         * Sets widget value
         * @param {String} value
         * @returns {String}
         */
        set: function set(value) {
          this.config.value = value;
          if (this.is('rendered')) {
            this.getElement().find('[name="' + this.config.uri + '"]').val(value);
          }
          return this.config.value;
        },
        /**
         * Add a validator
         * @param {ui/generis/validator/validator} validator
         * @returns {this}
         */
        setValidator: function setValidator(validator) {
          validator = validator || [];
          if (typeof validator.is === 'function') {
            // is a ui/component
            this.validator = validator;
          } else {
            this.validator = generisValidatorFactory({
              validations: validator
            });
          }
          if (this.is('rendered')) {
            this.validator.render(this.getElement());
          } else {
            this.on('render.setValidator', function () {
              this.validator.render(this.getElement());
              this.off('render.setValidator');
            });
          }
          return this;
        },
        /**
         * Validates widget (if validator is not null)
         * @returns {this}
         */
        validate: function validate() {
          var input;
          if (this.validator) {
            this.validator.run(this.get());
            this.validator.display();
            if (this.is('rendered')) {
              input = this.getElement().find('.right > :input, .right > .check-box-input');
              if (this.validator.errors.length) {
                input.addClass('error');
              } else {
                input.removeClass('error');
              }
            }
          }
          return this;
        },
        /**
         * Serializes widget into a name/value object for form submission
         * @returns {Object}
         */
        serialize: function serialize() {
          return {
            name: this.config.uri,
            value: this.get()
          };
        }
      }, spec), {
        label: __('Label'),
        required: false
      }).on('render', function () {
        var $input = this.getElement().find('.right :input');
        var self = this;
        $input.on('change blur', function () {
          /**
           * @event widget#change
           * @param {Object} widgetData
           */
          self.trigger('change', self.serialize());
        });
      });
      widget.setValidator(options.validator);
      return widget;
    }

    return factory;

});
