define(['jquery', 'lodash', 'i18n', 'ui/report', 'ui/feedback', 'layout/loading-bar', 'handlebars', 'lib/handlebars/helpers', 'css!ui/taskQueueButton/css/taskable.css'], function ($$1, _, __, reportFactory, feedback, loadingBar, Handlebars, Helpers0, taskable_css) { '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'] : __;
    reportFactory = reportFactory && Object.prototype.hasOwnProperty.call(reportFactory, 'default') ? reportFactory['default'] : reportFactory;
    feedback = feedback && Object.prototype.hasOwnProperty.call(feedback, 'default') ? feedback['default'] : feedback;
    loadingBar = loadingBar && Object.prototype.hasOwnProperty.call(loadingBar, 'default') ? loadingBar['default'] : loadingBar;
    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;


      buffer += "<div class=\"task-report-container\">\n    <div class=\"section-header flex-container-full\">\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    </div>\n    <div class=\"main-container flex-container-full report\"></div>\n</div>";
      return buffer;
      });
    function reportTpl(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;
     */
    var defaultConfig = {};
    var taskableComponent = {
      /**
       * Set configuration for task creation
       * @param config
       * @returns {taskableComponent}
       */
      setTaskConfig: function setTaskConfig(config) {
        _.assign(this.config, config);
        return this;
      },
      /**
       * Create a task
       * @param requestUrl
       * @param requestData
       */
      createTask: function createTask() {
        var self = this;
        var taskQueue,
          requestUrl,
          requestData = {};

        //prepare the request parameter if applicable
        if (_.isFunction(this.config.taskCreationData)) {
          requestData = this.config.taskCreationData.call(this);
        } else if (_.isPlainObject(this.config.taskCreationData)) {
          requestData = this.config.taskCreationData;
        }
        if (!this.config.taskCreationUrl) {
          return this.trigger('error', 'the request url is required to create a task');
        }
        requestUrl = this.config.taskCreationUrl;
        if (!this.config.taskQueue) {
          return this.trigger('error', 'the taskQueue model is required to create a task');
        }
        taskQueue = this.config.taskQueue;
        loadingBar.start();
        taskQueue.pollAllStop();
        taskQueue.create(requestUrl, requestData).then(function (result) {
          var infoBox,
            message,
            task = result.task;
          if (result.finished) {
            if (task.hasFile) {
              //download if its is a export-typed task
              taskQueue.download(task.id).then(function () {
                //immediately archive the finished task as there is no need to display this task in the queue list
                return taskQueue.archive(task.id);
              }).then(function () {
                self.trigger('finished', result);
                taskQueue.pollAll();
              }).catch(function (err) {
                self.trigger('error', err);
                taskQueue.pollAll();
              });
            } else {
              //immediately archive the finished task as there is no need to display this task in the queue list
              taskQueue.archive(task.id).then(function () {
                self.trigger('finished', result);
                taskQueue.pollAll();
              }).catch(function (err) {
                self.trigger('error', err);
                taskQueue.pollAll();
              });
            }
          } else {
            //enqueuing process:
            message = __('<strong> %s </strong> has been moved to the background.', task.taskLabel);
            infoBox = feedback(null, {
              encodeHtml: false,
              timeout: {
                info: 8000
              }
            }).info(message);
            taskQueue.trigger('taskcreated', {
              task: task,
              sourceDom: infoBox.getElement()
            });
            self.trigger('enqueued', result);
          }
          loadingBar.stop();
        }).catch(function (err) {
          //in case of error display it and continue task queue activity
          taskQueue.pollAll();
          loadingBar.stop();
          self.trigger('error', err);
        });
      },
      /**
       * prepare the given container to display the final report
       * @param {Object} report - the standard report object
       * @param {String} title - the report title
       * @param {String} result - raw result data from the task creation action
       * @param {boolean} displayContinueButton - display Continue button if true
       */
      displayReport: function displayReport(report, title, result) {
        let displayContinueButton = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
        var self = this,
          $reportContainer;
        let actions = [];
        if (displayContinueButton) {
          actions = [{
            id: 'continue',
            icon: 'right',
            title: 'continue',
            label: __('Continue')
          }];
        }
        if (this.config.taskReportContainer instanceof $$1) {
          $reportContainer = $$1(reportTpl({
            title: title
          }));
          this.config.taskReportContainer.html($reportContainer);
          return reportFactory({
            actions
          }, report).on('action-continue', function () {
            self.trigger('continue', result);
          }).render($reportContainer.find('.report'));
        }
      }
    };

    /**
     * @param {Component} component - an instance of ui/component
     * @param {Object} config - task queue creation specific config
     * @param {Object} config.taskQueue - the task queue model to be used
     * @param {String} config.taskCreationUrl - endpoint to create a task
     * @param {Object|Function} [config.taskCreationData] - the parameters that will be send to the task creation request
     * @param {JQuery} [config.taskReportContainer] - the container where the inline report can be printed to
     * @return {taskableComponent}
     */
    function makeTaskable(component, config) {
      _.assign(component, taskableComponent);

      /**
       * @typedef {ui/component} taskableComponent
       */
      return component.off('.taskable').on('init.taskable', function () {
        _.defaults(this.config, config || {}, defaultConfig);
      });
    }

    return makeTaskable;

});
