/**
 Interface for editing peer assessment settings.

 Args:
 element (DOM element): The DOM element representing this view.

 Returns:
 OpenAssessment.EditPeerAssessmentView

 **/
OpenAssessment.EditPeerAssessmentView = function(element) {
    this.element = element;
    this.name = 'peer-assessment';
    this.mustGradeField = new OpenAssessment.IntField(
        $('#peer_assessment_must_grade', this.element),
        {min: 0, max: 99}
    );
    this.mustBeGradedByField = new OpenAssessment.IntField(
        $('#peer_assessment_graded_by', this.element),
        {min: 0, max: 99}
    );

    // Configure the toggle checkbox to enable/disable this assessment
    new OpenAssessment.ToggleControl(
        $('#include_peer_assessment', this.element),
        $('#peer_assessment_settings_editor', this.element),
        $('#peer_assessment_description_closed', this.element),
        new OpenAssessment.Notifier([
            new OpenAssessment.AssessmentToggleListener(),
        ])
    ).install();

    // Configure the date and time fields
    this.startDatetimeControl = new OpenAssessment.DatetimeControl(
        this.element,
        '#peer_assessment_start_date',
        '#peer_assessment_start_time'
    ).install();

    this.dueDatetimeControl = new OpenAssessment.DatetimeControl(
        this.element,
        '#peer_assessment_due_date',
        '#peer_assessment_due_time'
    ).install();
};

OpenAssessment.EditPeerAssessmentView.prototype = {

    /**
     Return a description of the assessment.

     Returns:
     object literal

     Example usage:
     >>> editPeerView.description();
     {
         must_grade: 5,
         must_be_graded_by: 2,
         start: null,
         due: "2014-04-1T00:00"
     }
     **/
    description: function() {
        return {
            must_grade: this.mustGradeNum(),
            must_be_graded_by: this.mustBeGradedByNum(),
            start: this.startDatetime(),
            due: this.dueDatetime(),
        };
    },

    /**
     Get or set whether the assessment is enabled.

     Args:
     isEnabled (boolean, optional): If provided, set the enabled state of the assessment.

     Returns:
     boolean
     ***/
    isEnabled: function(isEnabled) {
        var sel = $('#include_peer_assessment', this.element);
        return OpenAssessment.Fields.booleanField(sel, isEnabled);
    },

    /**
     Toggle whether the assessment is enabled or disabled.
     This triggers the actual click event and is mainly useful for testing.
     **/
    toggleEnabled: function() {
        $('#include_peer_assessment', this.element).click();
    },

    /**
     Get or set the required number of submissions a student must peer-assess.

     Args:
     num (int, optional): If provided, set the required number of assessments.

     Returns:
     int
     **/
    mustGradeNum: function(num) {
        if (num !== undefined) {this.mustGradeField.set(num);}
        return this.mustGradeField.get();
    },

    /**
     Get or set the required number of peer-assessments a student must receive.

     Args:
     num (int, optional): If provided, set the required number of assessments.

     Returns:
     int
     **/
    mustBeGradedByNum: function(num) {
        if (num !== undefined) {this.mustBeGradedByField.set(num);}
        return this.mustBeGradedByField.get();
    },

    /**
     Get or set the start date and time of the assessment.

     Args:
     dateString (string, optional): If provided, set the date (YY-MM-DD).
     timeString (string, optional): If provided, set the time (HH:MM, 24-hour clock).

     Returns:
     string (ISO-formatted UTC datetime)
     **/
    startDatetime: function(dateString, timeString) {
        return this.startDatetimeControl.datetime(dateString, timeString);
    },

    /**
     Get or set the due date and time of the assessment.

     Args:
     dateString (string, optional): If provided, set the date (YY-MM-DD).
     timeString (string, optional): If provided, set the time (HH:MM, 24-hour clock).

     Returns:
     string (ISO-formatted UTC datetime)
     **/
    dueDatetime: function(dateString, timeString) {
        return this.dueDatetimeControl.datetime(dateString, timeString);
    },

    /**
     Gets the ID of the assessment

     Returns:
     string (CSS ID of the Element object)
     **/
    getID: function() {
        return $(this.element).attr('id');
    },

    /**
     Mark validation errors.

     Returns:
     Boolean indicating whether the view is valid.

     **/
    validate: function() {
        var startValid = this.startDatetimeControl.validate();
        var dueValid = this.dueDatetimeControl.validate();
        var mustGradeValid = this.mustGradeField.validate();
        var mustBeGradedByValid = this.mustBeGradedByField.validate();
        return startValid && dueValid && mustGradeValid && mustBeGradedByValid;
    },

    /**
     Return a list of validation errors visible in the UI.
     Mainly useful for testing.

     Returns:
     list of string

     **/
    validationErrors: function() {
        var errors = [];
        if (this.startDatetimeControl.validationErrors().length > 0) {
            errors.push('Peer assessment start is invalid');
        }
        if (this.dueDatetimeControl.validationErrors().length > 0) {
            errors.push('Peer assessment due is invalid');
        }
        if (this.mustGradeField.validationErrors().length > 0) {
            errors.push('Peer assessment must grade is invalid');
        }
        if (this.mustBeGradedByField.validationErrors().length > 0) {
            errors.push('Peer assessment must be graded by is invalid');
        }
        return errors;
    },

    /**
     Clear all validation errors from the UI.
     **/
    clearValidationErrors: function() {
        this.startDatetimeControl.clearValidationErrors();
        this.dueDatetimeControl.clearValidationErrors();
        this.mustGradeField.clearValidationErrors();
        this.mustBeGradedByField.clearValidationErrors();
    },
};

/**
 Interface for editing self assessment settings.

 Args:
 element (DOM element): The DOM element representing this view.

 Returns:
 OpenAssessment.EditSelfAssessmentView

 **/
OpenAssessment.EditSelfAssessmentView = function(element) {
    this.element = element;
    this.name = 'self-assessment';

    // Configure the toggle checkbox to enable/disable this assessment
    new OpenAssessment.ToggleControl(
        $('#include_self_assessment', this.element),
        $('#self_assessment_settings_editor', this.element),
        $('#self_assessment_description_closed', this.element),
        new OpenAssessment.Notifier([
            new OpenAssessment.AssessmentToggleListener(),
        ])
    ).install();

    // Configure the date and time fields
    this.startDatetimeControl = new OpenAssessment.DatetimeControl(
        this.element,
        '#self_assessment_start_date',
        '#self_assessment_start_time'
    ).install();

    this.dueDatetimeControl = new OpenAssessment.DatetimeControl(
        this.element,
        '#self_assessment_due_date',
        '#self_assessment_due_time'
    ).install();
};

OpenAssessment.EditSelfAssessmentView.prototype = {

    /**
     Return a description of the assessment.

     Returns:
     object literal

     Example usage:
     >>> editSelfView.description();
     {
         start: null,
         due: "2014-04-1T00:00"
     }

     **/
    description: function() {
        return {
            start: this.startDatetime(),
            due: this.dueDatetime(),
        };
    },

    /**
     Get or set whether the assessment is enabled.

     Args:
     isEnabled (boolean, optional): If provided, set the enabled state of the assessment.

     Returns:
     boolean
     ***/
    isEnabled: function(isEnabled) {
        var sel = $('#include_self_assessment', this.element);
        return OpenAssessment.Fields.booleanField(sel, isEnabled);
    },

    /**
     Toggle whether the assessment is enabled or disabled.
     This triggers the actual click event and is mainly useful for testing.
     **/
    toggleEnabled: function() {
        $('#include_self_assessment', this.element).click();
    },

    /**
     Get or set the start date and time of the assessment.

     Args:
     dateString (string, optional): If provided, set the date (YY-MM-DD).
     timeString (string, optional): If provided, set the time (HH:MM, 24-hour clock).

     Returns:
     string (ISO-formatted UTC datetime)
     **/
    startDatetime: function(dateString, timeString) {
        return this.startDatetimeControl.datetime(dateString, timeString);
    },

    /**
     Get or set the due date and time of the assessment.

     Args:
     dateString (string, optional): If provided, set the date (YY-MM-DD).
     timeString (string, optional): If provided, set the time (HH:MM, 24-hour clock).

     Returns:
     string (ISO-formatted UTC datetime)
     **/
    dueDatetime: function(dateString, timeString) {
        return this.dueDatetimeControl.datetime(dateString, timeString);
    },

    /**
     Gets the ID of the assessment

     Returns:
     string (CSS ID of the Element object)
     **/
    getID: function() {
        return $(this.element).attr('id');
    },

    /**
     Mark validation errors.

     Returns:
     Boolean indicating whether the view is valid.

     **/
    validate: function() {
        var startValid = this.startDatetimeControl.validate();
        var dueValid = this.dueDatetimeControl.validate();
        return startValid && dueValid;
    },

    /**
     Return a list of validation errors visible in the UI.
     Mainly useful for testing.

     Returns:
     list of string

     **/
    validationErrors: function() {
        var errors = [];
        if (this.startDatetimeControl.validationErrors().length > 0) {
            errors.push('Self assessment start is invalid');
        }
        if (this.dueDatetimeControl.validationErrors().length > 0) {
            errors.push('Self assessment due is invalid');
        }
        return errors;
    },

    /**
     Clear all validation errors from the UI.
     **/
    clearValidationErrors: function() {
        this.startDatetimeControl.clearValidationErrors();
        this.dueDatetimeControl.clearValidationErrors();
    },
};

/**
 Interface for editing student training assessment settings.

 Args:
 element (DOM element): The DOM element representing this view.

 Returns:
 OpenAssessment.EditStudentTrainingView

 **/
OpenAssessment.EditStudentTrainingView = function(element) {
    this.element = element;
    this.name = 'student-training';

    new OpenAssessment.ToggleControl(
        $('#include_student_training', this.element),
        $('#student_training_settings_editor', this.element),
        $('#student_training_description_closed', this.element),
        new OpenAssessment.Notifier([
            new OpenAssessment.AssessmentToggleListener(),
        ])
    ).install();

    this.exampleContainer = new OpenAssessment.Container(
        OpenAssessment.TrainingExample, {
            containerElement: $('#openassessment_training_example_list', this.element).get(0),
            templateElement: $('#openassessment_training_example_template', this.element).get(0),
            addButtonElement: $('.openassessment_add_training_example', this.element).get(0),
            removeButtonClass: 'openassessment_training_example_remove',
            containerItemClass: 'openassessment_training_example',
        }
    );

    this.exampleContainer.addEventListeners();
};

OpenAssessment.EditStudentTrainingView.prototype = {

    /**
     Return a description of the assessment.

     Returns:
     object literal

     Example usage:
     >>> editTrainingView.description();
     {
         examples: [
             {
                 answer: ("I love pokemon 1", "I love pokemon 2"),
                 options_selected: [
                     {
                         criterion: "brevity",
                         option: "suberb"
                     },
                         criterion: "accuracy",
                         option: "alright"
                     }
                     ...
                 ]
             },
     ...
     ]
     }
     **/
    description: function() {
        return {
            examples: this.exampleContainer.getItemValues(),
        };
    },

    /**
     Get or set whether the assessment is enabled.

     Args:
     isEnabled (boolean, optional): If provided, set the enabled state of the assessment.

     Returns:
     boolean
     ***/
    isEnabled: function(isEnabled) {
        var sel = $('#include_student_training', this.element);
        return OpenAssessment.Fields.booleanField(sel, isEnabled);
    },

    /**
     Toggle whether the assessment is enabled or disabled.
     This triggers the actual click event and is mainly useful for testing.
     **/
    toggleEnabled: function() {
        $('#include_student_training', this.element).click();
    },

    /**
     Gets the ID of the assessment

     Returns:
     string (CSS ID of the Element object)
     **/
    getID: function() {
        return $(this.element).attr('id');
    },

    /**
     Mark validation errors.

     Returns:
     Boolean indicating whether the view is valid.

     **/
    validate: function() {
        var isValid = true;

        $.each(this.exampleContainer.getAllItems(), function() {
            isValid = this.validate() && isValid;
        });

        return isValid;
    },

    /**
     Return a list of validation errors visible in the UI.
     Mainly useful for testing.

     Returns:
     list of string

     **/
    validationErrors: function() {
        var errors = [];
        $.each(this.exampleContainer.getAllItems(), function() {
            errors = errors.concat(this.validationErrors());
        });
        return errors;
    },

    /**
     Clear all validation errors from the UI.
     **/
    clearValidationErrors: function() {
        $.each(this.exampleContainer.getAllItems(), function() {
            this.clearValidationErrors();
        });
    },

    /**
     Adds a new training example by copying the training example template.
     Primarily used for testing.
     **/
    addTrainingExample: function() {
        this.exampleContainer.add();
    },
};

/**
 * Interface for editing staff assessment settings.
 *
 * @param {Object} element - The DOM element representing this view.
 * @constructor
 *
 */
OpenAssessment.EditStaffAssessmentView = function(element) {
    this.element = element;
    this.name = 'staff-assessment';

    // Configure the toggle checkbox to enable/disable this assessment
    new OpenAssessment.ToggleControl(
        $('#include_staff_assessment', this.element),
        $('#staff_assessment_description', this.element),
        $('#staff_assessment_description', this.element), // open and closed selectors are the same!
        new OpenAssessment.Notifier([
            new OpenAssessment.AssessmentToggleListener(),
        ])
    ).install();
};

OpenAssessment.EditStaffAssessmentView.prototype = {

    /**
     * Return a description of the assessment.
     *
     * @return {Object} Representation of the view.
     */
    description: function() {
        return {
            required: this.isEnabled(),
        };
    },

    /**
     * Get or set whether the assessment is enabled.
     *
     * @param {Boolean} isEnabled - If provided, set the enabled state of the assessment.
     * @return {Boolean}
     */
    isEnabled: function(isEnabled) {
        var sel = $('#include_staff_assessment', this.element);
        return OpenAssessment.Fields.booleanField(sel, isEnabled);
    },

    /**
     * Toggle whether the assessment is enabled or disabled.
     * This triggers the actual click event and is mainly useful for testing.
     */
    toggleEnabled: function() {
        $('#include_staff_assessment', this.element).click();
    },

    /**
     * Gets the ID of the assessment
     *
     * @return {String} CSS class of the Element object
     */
    getID: function() {
        return $(this.element).attr('id');
    },

    /**
     * Mark validation errors.
     *
     * @return {Boolean} Whether the view is valid.
     *
     */
    validate: function() {
        return true; // Nothing to validate, the only input is a boolean and either state is valid
    },

    /**
     * Return a list of validation errors visible in the UI.
     * Mainly useful for testing.
     *
     * @return {Array} - always empty, function called but not actually used.
     */
    validationErrors: function() {
        return [];
    },

    /**
     * Clear all validation errors from the UI.
     */
    clearValidationErrors: function() {
        // do nothing
    },
};
