text: var formioUtils = require('formiojs/utils');
  
  module.exports = function() {
    return {
      checkVisible: function(component, row, data) {
        var visible = formioUtils.checkCondition(component, row, data);
        if (!visible) {
          if (!component.hasOwnProperty('clearOnHide') || component.clearOnHide.toString() === 'true') {
            if (row && row.hasOwnProperty(component.key)) {
              delete row[component.key];
            }
            if (data && data.hasOwnProperty(component.key)) {
              delete data[component.key];
            }
          }
          return false;
        }
        return true;
      },
      isVisible: function(component, row, data, hide) {
        // If the component is in the hideComponents array, then hide it by default.
        if (hide && Array.isArray(hide) && (hide.indexOf(component.key) !== -1)) {
          return false;
        }
  
        return this.checkVisible(component, row, data);
      },
      flattenComponents: formioUtils.flattenComponents,
      eachComponent: formioUtils.eachComponent,
      getComponent: formioUtils.getComponent,
      getValue: formioUtils.getValue,
      hideFields: function(form, components) {
        this.eachComponent(form.components, function(component) {
          for (var i in components) {
            if (component.key === components[i]) {
              component.type = 'hidden';
            }
          }
        });
      },
      uniqueName: function(name) {
        var parts = name.toLowerCase().replace(/[^0-9a-z\.]/g, '').split('.');
        var fileName = parts[0];
        var ext = '';
        if (parts.length > 1) {
          ext = '.' + parts[(parts.length - 1)];
        }
        return fileName.substr(0, 10) + '-' + this.guid() + ext;
      },
      guid: function() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
          var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
          return v.toString(16);
        });
      },
      fieldWrap: function(input) {
        var multiInput = input.replace('data[component.key]', 'data[component.key][$index]');
        var inputLabel = '<label ng-if="component.label && !component.hideLabel" for="{{ component.key }}" class="control-label" ng-class="{\'field-required\': isRequired(component)}">{{ component.label | formioTranslate:null:builder }}</label>';
        var requiredInline = '<span ng-if="(component.hideLabel === true || component.label === \'\' || !component.label) && isRequired(component)" class="glyphicon glyphicon-asterisk form-control-feedback field-required-inline" aria-hidden="true"></span>';
        var template =
          '<div ng-if="!component.multiple">' +
            inputLabel +
            '<div class="input-group">' +
              '<div class="input-group-addon" ng-if="!!component.prefix">{{ component.prefix }}</div>' +
              input +
              requiredInline +
              '<div class="input-group-addon" ng-if="!!component.suffix">{{ component.suffix }}</div>' +
            '</div>' +
            '<div class="formio-errors">' +
              '<formio-errors ng-if="::!builder"></formio-errors>' +
            '</div>' +
          '</div>' +
          '<div ng-if="!!component.description" class="help-block">' +
            '<span>{{ component.description }}</span>' +
          '</div>' +
          '<div ng-if="component.multiple"><table class="table table-bordered">' +
            inputLabel +
            '<tr ng-repeat="value in data[component.key] track by $index">' +
              '<td>' +
                '<div class="input-group">' +
                  '<div class="input-group-addon" ng-if="!!component.prefix">{{ component.prefix }}</div>' +
                    multiInput +
                    requiredInline +
                  '<div class="input-group-addon" ng-if="!!component.suffix">{{ component.suffix }}</div>' +
                '</div>' +
                '<div class="formio-errors">' +
                  '<formio-errors ng-if="::!builder"></formio-errors>' +
                '</div>' +
              '</td>' +
              '<td><a ng-click="removeFieldValue($index)" class="btn btn-default"><span class="glyphicon glyphicon-remove-circle"></span></a></td>' +
            '</tr>' +
            '<tr>' +
              '<td colspan="2"><a ng-click="addFieldValue()" class="btn btn-primary"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> {{ component.addAnother || "Add Another" | formioTranslate:null:builder }}</a></td>' +
            '</tr>' +
          '</table></div>';
        return template;
      },
  
      /**
       * Check if a component is required
       *
       * @param {Object} component The component to be checked
       * @param {Array} componentsToRequire An array of component keys manually set to mark specific components as required
       */
      isRequired: function(component, componentsToRequire) {
        return (component.validate && component.validate.required) || (Array.isArray(componentsToRequire) && componentsToRequire.indexOf(component.key) !== -1);
      }
    };
  };
  