if (!CMS.Models['Settings']) CMS.Models.Settings = new Object();

CMS.Models.Settings.CourseGradingPolicy = Backbone.Model.extend({
	defaults : {	
		course_location : null,
		graders : null,  // CourseGraderCollection 
		grade_cutoffs : null,  // CourseGradeCutoff model
        grace_period : null // either null or { hours: n, minutes: m, ...}
	},
	parse: function(attributes) {
		if (attributes['course_location']) {
			attributes.course_location = new CMS.Models.Location(attributes.course_location, {parse:true});
		}
		if (attributes['graders']) {
			var graderCollection;
			if (this.has('graders')) {
				graderCollection = this.get('graders');
				graderCollection.reset(attributes.graders);
			}
			else {
				graderCollection = new CMS.Models.Settings.CourseGraderCollection(attributes.graders);
				graderCollection.course_location = attributes['course_location'] || this.get('course_location');
			}
			attributes.graders = graderCollection;
		}
		return attributes;
	},
	url : function() {
		var location = this.get('course_location');
		return '/' + location.get('org') + "/" + location.get('course') + '/settings/' + location.get('name') + '/section/grading';
	},
	gracePeriodToDate : function() {
		var newDate = new Date();
		if (this.has('grace_period') && this.get('grace_period')['hours'])
			newDate.setHours(this.get('grace_period')['hours']);
		else newDate.setHours(0);
		if (this.has('grace_period') && this.get('grace_period')['minutes'])
			newDate.setMinutes(this.get('grace_period')['minutes']);
		else newDate.setMinutes(0);
		if (this.has('grace_period') && this.get('grace_period')['seconds'])
			newDate.setSeconds(this.get('grace_period')['seconds']);
		else newDate.setSeconds(0);
		
		return newDate;
	},
	dateToGracePeriod : function(date) {
		return {hours : date.getHours(), minutes : date.getMinutes(), seconds : date.getSeconds() };
	}
});

CMS.Models.Settings.CourseGrader = Backbone.Model.extend({
	defaults: {
        "type" : "",	// must be unique w/in collection (ie. w/in course)
        "min_count" : 1,
        "drop_count" : 0,
        "short_label" : "",	// what to use in place of type if space is an issue 
        "weight" : 0 // int 0..100
    },
    parse : function(attrs) {
    	if (attrs['weight']) {
    		if (!_.isNumber(attrs.weight)) attrs.weight = parseInt(attrs.weight);
    	}
    	if (attrs['min_count']) {
    		if (!_.isNumber(attrs.min_count)) attrs.min_count = parseInt(attrs.min_count);
    	}
    	if (attrs['drop_count']) {
    		if (!_.isNumber(attrs.drop_count)) attrs.drop_count = parseInt(attrs.drop_count);
    	}
    	return attrs;
    },
    validate : function(attrs) {
    	var errors = {};
    	if (attrs['type']) {
    		if (_.isEmpty(attrs['type'])) {
    			errors.type = "The assignment type must have a name.";
    		}
    		else {
    			// FIXME somehow this.collection is unbound sometimes. I can't track down when
    			var existing = this.collection && this.collection.some(function(other) { return (other != this) && (other.get('type') == attrs['type']);}, this);
    			if (existing) {
    				errors.type = "There's already another assignment type with this name.";
    			}
    		}
    	}
    	if (attrs['weight']) {
    		if (!isFinite(attrs.weight) || /\D+/.test(attrs.weight)) {
    			errors.weight = "Please enter an integer between 0 and 100.";
    		}
    		else {
    			attrs.weight = parseInt(attrs.weight); // see if this ensures value saved is int
    			if (this.collection && attrs.weight > 0) {
    				// FIXME b/c saves don't update the models if validation fails, we should
    				// either revert the field value to the one in the model and make them make room
    				// or figure out a wholistic way to balance the vals across the whole
//    				if ((this.collection.sumWeights() + attrs.weight - this.get('weight')) > 100)
//    					errors.weight = "The weights cannot add to more than 100.";
    			}
    	}}
    	if (attrs['min_count']) {
    		if (!isFinite(attrs.min_count) || /\D+/.test(attrs.min_count)) {
    			errors.min_count = "Please enter an integer.";
    		}
    		else attrs.min_count = parseInt(attrs.min_count);
    	}
    	if (attrs['drop_count']) {
    		if (!isFinite(attrs.drop_count) || /\D+/.test(attrs.drop_count)) {
    			errors.drop_count = "Please enter an integer.";
    		}
    		else attrs.drop_count = parseInt(attrs.drop_count);
    	}
    	if (attrs['min_count'] && attrs['drop_count'] && attrs.drop_count > attrs.min_count) {
    		errors.drop_count = "Cannot drop more " + attrs.type + " than will assigned.";
    	}
		if (!_.isEmpty(errors)) return errors;
    }
});

CMS.Models.Settings.CourseGraderCollection = Backbone.Collection.extend({
	model : CMS.Models.Settings.CourseGrader,
	course_location : null, // must be set to a Location object
	url : function() {
		return '/' + this.course_location.get('org') + "/" + this.course_location.get('course') + '/grades/' + this.course_location.get('name') + '/';
	},
	sumWeights : function() {
		return this.reduce(function(subtotal, grader) { return subtotal + grader.get('weight'); }, 0);
	}
});