define(['jquery', 'lodash', 'i18n', 'ui/component', 'ui/dialog/confirm', 'ui/resource/selector', 'ui/loadingButton/loadingButton', 'ui/taskQueueButton/standardButton', 'handlebars', 'lib/handlebars/helpers', 'css!ui/destination/css/selector.css', 'lib/uuid'], function ($$1, _, __, component, confirmDialog, resourceSelectorFactory, loadingButtonFactory, taskCreationButtonFactory, Handlebars, Helpers0, selector_css, uuid) { 'use strict';

    $$1 = $$1 && Object.prototype.hasOwnProperty.call($$1, 'default') ? $$1['default'] : $$1;
    _ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _;
    __ = __ && Object.prototype.hasOwnProperty.call(__, 'default') ? __['default'] : __;
    component = component && Object.prototype.hasOwnProperty.call(component, 'default') ? component['default'] : component;
    confirmDialog = confirmDialog && Object.prototype.hasOwnProperty.call(confirmDialog, 'default') ? confirmDialog['default'] : confirmDialog;
    resourceSelectorFactory = resourceSelectorFactory && Object.prototype.hasOwnProperty.call(resourceSelectorFactory, 'default') ? resourceSelectorFactory['default'] : resourceSelectorFactory;
    loadingButtonFactory = loadingButtonFactory && Object.prototype.hasOwnProperty.call(loadingButtonFactory, 'default') ? loadingButtonFactory['default'] : loadingButtonFactory;
    taskCreationButtonFactory = taskCreationButtonFactory && Object.prototype.hasOwnProperty.call(taskCreationButtonFactory, 'default') ? taskCreationButtonFactory['default'] : taskCreationButtonFactory;
    Handlebars = Handlebars && Object.prototype.hasOwnProperty.call(Handlebars, 'default') ? Handlebars['default'] : Handlebars;
    Helpers0 = Helpers0 && Object.prototype.hasOwnProperty.call(Helpers0, 'default') ? Helpers0['default'] : Helpers0;
    uuid = uuid && Object.prototype.hasOwnProperty.call(uuid, 'default') ? uuid['default'] : uuid;

    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, functionType="function", escapeExpression=this.escapeExpression, helperMissing=helpers.helperMissing, self=this;

    function program1(depth0,data) {
      
      var buffer = "", stack1, helper;
      buffer += "\n    <h2>";
      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)
        + "</h2>\n    ";
      return buffer;
      }

    function program3(depth0,data) {
      
      var buffer = "", stack1, helper;
      buffer += "\n        <p class=\"section-title\">";
      if (helper = helpers.description) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.description); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "</p>\n        ";
      return buffer;
      }

    function program5(depth0,data) {
      
      var buffer = "", stack1, helper, options;
      buffer += "\n        <div class=\"permissions-settings-container\">\n            <p class=\"section-title\">"
        + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Permission settings", options) : helperMissing.call(depth0, "__", "Permission settings", options)))
        + "</p>\n            <input type=\"radio\" name=\"acl-mode\" id=\"acl-keep-original";
      if (helper = helpers.uniqId) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.uniqId); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "\" class=\"acl-keep-original\" ";
      stack1 = (helper = helpers.equal || (depth0 && depth0.equal),options={hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data},helper ? helper.call(depth0, (depth0 && depth0.aclTransferMode), "acl.keep.original", options) : helperMissing.call(depth0, "equal", (depth0 && depth0.aclTransferMode), "acl.keep.original", options));
      if(stack1 || stack1 === 0) { buffer += stack1; }
      buffer += " value=\"acl.keep.original\" />\n            <label for=\"acl-keep-original";
      if (helper = helpers.uniqId) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.uniqId); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "\">"
        + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Keep the original permissions", options) : helperMissing.call(depth0, "__", "Keep the original permissions", options)))
        + "</label><br>\n            <input type=\"radio\" name=\"acl-mode\" id=\"acl-use-destination";
      if (helper = helpers.uniqId) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.uniqId); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "\" class=\"acl-use-destination\" ";
      stack1 = (helper = helpers.equal || (depth0 && depth0.equal),options={hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data},helper ? helper.call(depth0, (depth0 && depth0.aclTransferMode), "acl.use.destination", options) : helperMissing.call(depth0, "equal", (depth0 && depth0.aclTransferMode), "acl.use.destination", options));
      if(stack1 || stack1 === 0) { buffer += stack1; }
      buffer += " value=\"acl.use.destination\" />\n            <label for=\"acl-use-destination";
      if (helper = helpers.uniqId) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.uniqId); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "\">"
        + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Inherit the permission of the parent folder", options) : helperMissing.call(depth0, "__", "Inherit the permission of the parent folder", options)))
        + "</label>\n        </div>\n        ";
      return buffer;
      }
    function program6(depth0,data) {
      
      
      return "checked ";
      }

      buffer += "<div class=\"destination-selector\">\n    ";
      stack1 = helpers['if'].call(depth0, (depth0 && depth0.title), {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
      if(stack1 || stack1 === 0) { buffer += stack1; }
      buffer += "\n    <div>\n        ";
      stack1 = helpers['if'].call(depth0, (depth0 && depth0.description), {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
      if(stack1 || stack1 === 0) { buffer += stack1; }
      buffer += "\n        <div class=\"selector-container\"></div>\n        ";
      stack1 = helpers['if'].call(depth0, (depth0 && depth0.showACL), {hash:{},inverse:self.noop,fn:self.program(5, program5, data),data:data});
      if(stack1 || stack1 === 0) { buffer += stack1; }
      buffer += "\n        <div class=\"actions\">\n        </div>\n    </div>\n</div>\n";
      return buffer;
      });
    function selectorTpl(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) 2018-2019 (original work) Open Assessment Technologies SA ;
     */
    var defaultConfig = {
      title: __('Copy to'),
      description: __('Select a destination'),
      actionName: __('Copy'),
      icon: 'copy',
      showACL: false,
      aclTransferMode: null
    };

    /**
     * Creates the selector component
     * @param {jQueryElement} $container - where the component is rendered
     * @param {Object} [config] - the configuration
     * @param {String} [config.classUri] - the root classUri
     * @param {String} [config.title] - header
     * @param {String} [config.description] - a description sentence
     * @param {String} [config.confirm] - when defined, confirmation message that will be displayed before triggering the action
     * @param {String} [config.actionName] - the action button text
     * @param {String} [config.icon] - the action button icon
     * @param {Object} [config.taskQueue] - define the taskQueue model to be used (only useful if the triggered action uses the task queue)
     * @param {String} [config.taskCreationUrl] - the task creation endpoint (only required if the option taskQueue is defined)
     * @param {Object} [config.taskCreationData] - optionally define the data that will be sent to the task creation endpoint
     * @param {Boolean} [config.showACL] - optionally define if ACL controls shall appear on the interface
     * @param {String} [config.aclTransferMode] - define ACL default behavior on the interface
     * @param {Function} [config.preventSelection] - prevent selection callback (@see ui/resource/selectable)
     * @returns {destinationSelector} the component itself
     */
    function destinationSelectorFactory($container, config) {
      /**
       * @typedef {destinationSelector} the component
       */
      var destinationSelector = component({
        /**
         * Forwards data update to it's resource selector
         * @see ui/resource/selector#update
         */
        update: function udpate(results, params) {
          if (this.resourceSelector) {
            this.resourceSelector.update(results, params);
          }
        },
        /**
         * Updates the url on taskCreationButton
         * @param {String} url - url of the task creation
         */
        updateTaskCreationUrl: function updateTaskCreationUrl(url) {
          if (this.config && this.taskCreationButton && this.taskCreationButton.config) {
            this.taskCreationButton.config.taskCreationUrl = url;
            this.config.taskCreationUrl = url;
          }
        }
      }, defaultConfig).setTemplate(selectorTpl).on('init', function () {
        this.config.uniqId = uuid(8);
        this.render($container);
      }).on('render', function () {
        var self = this;
        var $component = this.getElement();

        /**
         * Get the current selected class uri
         * @returns {String} the selected uri
         */
        const getSelectedUri = () => {
          var select = self.resourceSelector.getSelection();
          var uris;
          //validate the selection
          if (_.isPlainObject(select)) {
            uris = _.map(select, 'uri');
            if (uris.length) {
              return uris[0];
            }
          }
        };
        const getSelectedACLTransferMode = () => $$1('input[name="acl-mode"]:checked', $component).val();
        if (this.config.taskQueue) {
          this.taskCreationButton = taskCreationButtonFactory({
            type: 'info',
            icon: this.config.icon,
            label: this.config.actionName,
            terminatedLabel: 'Interrupted',
            taskQueue: this.config.taskQueue,
            taskCreationData: this.config.taskCreationData || {},
            taskCreationUrl: this.config.taskCreationUrl,
            taskReportContainer: $container
          }).on('finished', function (result) {
            self.trigger('finished', result, self.taskCreationButton);
            this.reset(); //reset the button
          }).on('continue', function () {
            self.trigger('continue');
          });
        } else {
          this.taskCreationButton = loadingButtonFactory({
            type: 'info',
            icon: this.config.icon,
            label: this.config.actionName,
            terminatedLabel: 'Interrupted'
          });
        }
        this.taskCreationButton.on('started', function () {
          function triggerAction() {
            /**
             * @event destinationSelector#select
             * @param {String} classUri - the destination class
             */
            self.trigger('select', getSelectedUri(), getSelectedACLTransferMode());
          }
          if (self.config.confirm) {
            confirmDialog(self.config.confirm, triggerAction, function () {
              self.taskCreationButton.terminate().reset();
            });
          } else {
            triggerAction();
          }
        }).on('error', function (err) {
          self.trigger('error', err);
        }).render($component.find('.actions')).disable();

        //set up the inner resource selector
        this.resourceSelector = resourceSelectorFactory($$1('.selector-container', $component), {
          selectionMode: 'single',
          selectClass: true,
          classUri: this.config.classUri,
          showContext: false,
          showSelection: false,
          preventSelection: this.config.preventSelection
        });

        //spread the events
        this.resourceSelector.spread(this, ['query', 'error', 'update']);

        //enable disable the action button
        this.resourceSelector.on('change', function (selected) {
          if (selected && _.size(selected) > 0) {
            self.taskCreationButton.enable();

            //append the selected class URI to the task creation data
            if (_.isPlainObject(self.taskCreationButton.config.taskCreationData)) {
              self.taskCreationButton.config.taskCreationData.classUri = getSelectedUri();
            }
          } else {
            self.taskCreationButton.disable();
          }
        });
      });
      _.defer(function () {
        destinationSelector.init(config);
      });
      return destinationSelector;
    }

    return destinationSelectorFactory;

});
