text: define([
    'core/js/adapt',
    'core/js/enums/completionStateEnum'
  ], function(Adapt, COMPLETION_STATE) {
  
    var Tracking = Backbone.Controller.extend({
  
      _config: {
        _requireContentCompleted: true,
        _requireAssessmentCompleted: false
      },
  
      _assessmentState: null,
  
      initialize: function() {
        Adapt.once('configModel:dataLoaded', this.loadConfig.bind(this));
        Adapt.on('app:dataReady', this.setupEventListeners.bind(this));
      },
  
      setupEventListeners: function() {
        // Check if completion requires passing an assessment.
        if (this._config._requireAssessmentCompleted) {
          this.listenTo(Adapt, {
            'assessment:complete': this.onAssessmentComplete,
            'assessment:restored': this.onAssessmentRestored
          });
        }
  
        // Check if completion requires completing all content.
        if (this._config._requireContentCompleted) {
          this.listenTo(Adapt.course, 'change:_isComplete', this.checkCompletion);
        }
      },
  
      /**
       * Store the assessment state.
       * @param {object} assessmentState - The object returned by Adapt.assessment.getState()
       */
      onAssessmentComplete: function(assessmentState) {
        this._assessmentState = assessmentState;
  
        this.checkCompletion();
      },
  
      /**
       * Restores the _assessmentState object when an assessment is registered.
       * @param {object} assessmentState - An object representing the overall assessment state
       */
      onAssessmentRestored: function(assessmentState) {
        this._assessmentState = assessmentState;
      },
  
      /**
       * Evaluate the course and assessment completion.
       */
      checkCompletion: function() {
        var completionData = this.getCompletionData();
  
        if (completionData.status === COMPLETION_STATE.INCOMPLETE) {
          return;
        }
  
        Adapt.trigger('tracking:complete', completionData);
        Adapt.log.debug('tracking:complete', completionData);
      },
  
      /**
       * The return value of this function should be passed to the trigger of 'tracking:complete'.
       * @returns An object representing the user's course completion.
       */
      getCompletionData: function() {
        var completionData = {
          status: COMPLETION_STATE.INCOMPLETE,
          assessment: null
        };
  
        // Course complete is required.
        if (this._config._requireContentCompleted && !Adapt.course.get('_isComplete')) {
          // INCOMPLETE: course not complete.
          return completionData;
        }
  
        // Assessment completed required.
        if (this._config._requireAssessmentCompleted) {
          if (!this._assessmentState) {
            // INCOMPLETE: assessment is not complete.
            return completionData;
          }
  
          // PASSED/FAILED: assessment completed.
          completionData.status = this._assessmentState.isPass ? COMPLETION_STATE.PASSED : COMPLETION_STATE.FAILED;
          completionData.assessment = this._assessmentState;
  
          return completionData;
        }
  
        // COMPLETED: criteria met, no assessment requirements.
        completionData.status = COMPLETION_STATE.COMPLETED;
  
        return completionData;
      },
  
      /**
       * Set the _config object to the values retrieved from config.json.
       */
      loadConfig: function() {
        if (Adapt.config.has('_completionCriteria')) {
          this._config = Adapt.config.get('_completionCriteria');
        }
      }
  
    });
  
    Adapt.tracking = new Tracking();
  
    return Adapt.tracking;
  
  });
  