define(['jquery', 'lodash', 'taoTests/runner/plugin', 'handlebars', 'lib/handlebars/helpers', 'taoQtiTest/runner/helpers/map', 'taoQtiTest/runner/helpers/getTimerMessage', 'moment', 'taoQtiTest/runner/helpers/stats'], function ($$1, _, pluginFactory, Handlebars, Helpers0, mapHelper, getTimerMessage, moment, statsHelper) { 'use strict';

    $$1 = $$1 && Object.prototype.hasOwnProperty.call($$1, 'default') ? $$1['default'] : $$1;
    _ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _;
    pluginFactory = pluginFactory && Object.prototype.hasOwnProperty.call(pluginFactory, 'default') ? pluginFactory['default'] : pluginFactory;
    Handlebars = Handlebars && Object.prototype.hasOwnProperty.call(Handlebars, 'default') ? Handlebars['default'] : Handlebars;
    Helpers0 = Helpers0 && Object.prototype.hasOwnProperty.call(Helpers0, 'default') ? Helpers0['default'] : Helpers0;
    mapHelper = mapHelper && Object.prototype.hasOwnProperty.call(mapHelper, 'default') ? mapHelper['default'] : mapHelper;
    getTimerMessage = getTimerMessage && Object.prototype.hasOwnProperty.call(getTimerMessage, 'default') ? getTimerMessage['default'] : getTimerMessage;
    moment = moment && Object.prototype.hasOwnProperty.call(moment, 'default') ? moment['default'] : moment;
    statsHelper = statsHelper && Object.prototype.hasOwnProperty.call(statsHelper, 'default') ? statsHelper['default'] : statsHelper;

    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, self=this;

    function program1(depth0,data) {
      
      var buffer = "", stack1, helper;
      buffer += "\n        <span data-control=\"";
      if (helper = helpers.attribute) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.attribute); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "\" class=\"qti-controls ";
      if (helper = helpers.className) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.className); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "\"></span>\n        <div data-control=\"";
      if (helper = helpers.attribute) { stack1 = helper.call(depth0, {hash:{},data:data}); }
      else { helper = (depth0 && depth0.attribute); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
      buffer += escapeExpression(stack1)
        + "-timer\" class=\"visible-hidden\"></div>\n    ";
      return buffer;
      }

      buffer += "<div role=\"heading\" aria-level=\"1\" class=\"title-box truncate\">\n    ";
      stack1 = helpers.each.call(depth0, (depth0 && depth0.titles), {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
      if(stack1 || stack1 === 0) { buffer += stack1; }
      buffer += "\n</div>\n";
      return buffer;
      });
    function titleTpl(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) 2016 (original work) Open Assessment Technologies SA ;
     */
    const precision = 1000;
    var title = pluginFactory({
      name: 'title',
      init: function init() {
        const testRunner = this.getTestRunner();
        const testMap = testRunner.getTestMap();
        const updateTitles = () => {
          const testContext = testRunner.getTestContext();
          const currentPart = mapHelper.getItemPart(testMap, testContext.itemPosition);
          const currentItem = mapHelper.getItem(testMap, testContext.itemIdentifier);

          // update test title
          if (testMap.title) {
            this.titles.test.$title.text(testMap.title).show();
          }

          // update part title
          if (currentPart && currentPart.label) {
            this.titles.testPart.$title.text(` - ${currentPart.label}`).show();
          }

          // update section title
          //@deprecated the following block seems to
          //be very specific and need to be reworked
          if (testContext.isDeepestSectionVisible) {
            const section = mapHelper.getItemSection(testMap, testContext.itemPosition);

            //testContext.sectionTitle is kept only for backward compat
            this.titles.section.$title.text(` - ${section.label || testContext.sectionTitle}`).show();
          }

          // update item title
          if (currentItem.label) {
            this.titles.item.$title.text(` - ${currentItem.label}`).show();
          }
        };
        testRunner.after('renderitem', () => {
          _.forOwn(this.titles, (options, scope) => {
            this.titles[scope].$title.text('');
            this.titles[scope].$timer.text('');
            if (scope !== 'item') {
              this.titles[scope].stats = statsHelper.getInstantStats(scope, testRunner);
            }
          });
          updateTitles();
        }).on('timertick', (remainingTime, scope) => {
          const title = this.titles[scope];
          if (!title) {
            return;
          }
          const {
            $timer,
            stats
          } = this.titles[scope];
          const time = moment.duration(remainingTime / precision, 'seconds');
          const hours = time.get('hours');
          const minutes = time.get('minutes');
          const seconds = time.get('seconds');
          const unansweredQuestions = stats && stats.questions - stats.answered;

          // check if notification should be updated
          if ($timer) {
            $timer.text(getTimerMessage(hours, minutes, seconds, unansweredQuestions));
          }
        }).on('unloaditem', () => {
          $$1('.qti-controls', this.$element).hide();
        });
      },
      render: function render() {
        const $container = this.getAreaBroker().getControlArea();
        this.titles = {
          test: {
            attribute: 'qti-test-title',
            className: ''
          },
          testPart: {
            attribute: 'qti-test-part-title',
            className: 'visible-hidden'
          },
          section: {
            attribute: 'qti-test-position',
            className: ''
          },
          item: {
            attribute: 'qti-test-item-title',
            className: 'visible-hidden'
          }
        };
        this.$element = $$1(titleTpl({
          titles: _.values(this.titles)
        }));

        // hide titles by default
        $$1('.qti-controls', this.$element).hide();
        $container.append(this.$element);
        _.forOwn(this.titles, (_ref, scope) => {
          let {
            attribute
          } = _ref;
          this.titles[scope].$title = $container.find(`[data-control="${attribute}"]`);
          this.titles[scope].$timer = $container.find(`[data-control="${attribute}-timer"]`);
        });
      }
    });

    return title;

});
