define(['lodash', 'i18n', 'handlebars', 'lib/handlebars/helpers'], function (_, __, Handlebars, Helpers0) { 'use strict';

    _ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _;
    __ = __ && Object.prototype.hasOwnProperty.call(__, 'default') ? __['default'] : __;
    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); partials = this.merge(partials, Handlebars.partials); data = data || {};
      var buffer = "", stack1, helper, functionType="function", escapeExpression=this.escapeExpression, self=this;


      buffer += "<div class=\"form-widget ";
      if (helper = helpers.widgetType) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.widgetType); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "\">\n    <div class=\"widget-label\">\n        ";
      stack1 = self.invokePartial(partials['ui-form-widget-label'], 'ui-form-widget-label', depth0, helpers, partials, data);
      if(stack1 || stack1 === 0) { buffer += stack1; }
      buffer += "\n    </div>\n    <div class=\"widget-field\">\n        <input class=\"widget-input-inline\" type=\"password\" name=\"";
      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    </div>\n</div>\n\n<div class=\"form-widget ";
      if (helper = helpers.widgetType) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.widgetType); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + " confirmation\">\n    <div class=\"widget-label\">\n        ";
      stack1 = self.invokePartial(partials['ui-form-widget-label'], 'ui-form-widget-label', (depth0 && depth0.confirmation), helpers, partials, data);
      if(stack1 || stack1 === 0) { buffer += stack1; }
      buffer += "\n    </div>\n    <div class=\"widget-field\">\n        <input class=\"widget-input-inline\" type=\"password\" name=\""
        + escapeExpression(((stack1 = ((stack1 = (depth0 && depth0.confirmation)),stack1 == null || stack1 === false ? stack1 : stack1.uri)),typeof stack1 === functionType ? stack1.apply(depth0) : stack1))
        + "\" />\n    </div>\n</div>\n";
      return buffer;
      });
    function hiddenBoxTpl(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) 2019 Open Assessment Technologies SA ;
     */

    /**
     * @typedef {widgetConfig} hiddenBoxConfig Defines the config entries available to setup a hiddenBox form widget
     * @property {Object} [confirmation] - confirmation label, uri and value
     */

    /**
     * Defines the provider for a hiddenBox widget.
     *
     * @example
     * import widgetHiddenBoxProvider from 'ui/form/widget/providers/hiddenBox';
     * widgetFactory.registerProvider('hiddenBox', widgetHiddenBoxProvider);
     * const widget = widgetFactory(container, {
     *     widget: 'hiddenBox'
     *     uri: 'hb',
     *     label: 'Password',
     *     confirmation: {
     *         label: 'Please confirm'
     *     }
     * });
     */
    const widgetHiddenBoxProvider = {
      /**
       * Initialize the widget.
       * @param {hiddenBoxConfig} config
       */
      init(config) {
        // the type will be reflected to the HTML markup
        config.widgetType = 'hidden-box';

        // config for the confirmation field
        config.confirmation = _.defaults(config.confirmation || {}, {
          label: __('%s Confirmation', config.label),
          uri: config.uri + '_confirmation',
          value: config.value || ''
        });
      },
      /**
       * Resets the widget to the default validators
       */
      setDefaultValidators() {
        // set default validator if the field is required
        if (this.getConfig().required) {
          this.getValidator().addValidation({
            id: 'required',
            message: __('This field is required'),
            predicate: value => /\S+/.test(value.value),
            precedence: 1
          });
        }

        // add validation for the confirmation field
        this.getValidator().addValidation({
          id: 'confirmation',
          message: __('Fields must match'),
          predicate: value => value.value === value.confirmation,
          precedence: 2
        });
      },
      /**
       * Gets the value of the widget
       * @returns {String}
       */
      getValue() {
        let value = this.getConfig().value;
        if (this.is('rendered')) {
          value = this.getElement().find(`[name="${this.getUri()}"]`).val();
        }
        return value;
      },
      /**
       * Gets the raw value of the widget
       * @returns {*}
       */
      getRawValue() {
        const value = {
          value: this.getValue(),
          confirmation: this.getConfig().confirmation.value
        };
        if (this.is('rendered')) {
          value.confirmation = this.getElement().find(`[name="${this.getConfig().confirmation.uri}"]`).val();
        }
        return value;
      },
      /**
       * Sets the value of the widget
       * @param {String} value
       */
      setValue(value) {
        if (this.is('rendered')) {
          const $input = this.getElement().find(`[name="${this.getUri()}"]`);
          const $confirmation = this.getElement().find(`[name="${this.getConfig().confirmation.uri}"]`);
          if ($input.val() === $confirmation.val()) {
            this.getConfig().confirmation.value = value;
            $confirmation.val(value);
          }
          $input.val(value);
        } else {
          this.getConfig().confirmation.value = value;
        }
      },
      /**
       * Gets access to the actual form element
       * @returns {jQuery|null}
       */
      getWidgetElement() {
        return this.getElement().find('input');
      },
      /**
       * Expose the template to the factory and it will apply it
       */
      template: hiddenBoxTpl
    };

    return widgetHiddenBoxProvider;

});
