define(['backbone', 'underscore'], function(Backbone, _) {
    var LicenseModel = Backbone.Model.extend({
        defaults: {
            type: null,
            options: {},
            custom: false // either `false`, or a string
        },

        initialize: function(attributes) {
            if (attributes && attributes.asString) {
                this.setFromString(attributes.asString);
                this.unset('asString');
            }
        },

        toString: function() {
            var custom = this.get('custom');
            if (custom) {
                return custom;
            }

            var type = this.get('type'),
                options = this.get('options');

            if (_.isEmpty(options)) {
                return type || '';
            }

            // options are where it gets tricky
            var optionStrings = _.map(options, function(value, key) {
                if (_.isBoolean(value)) {
                    return value ? key : null;
                } else {
                    return key + '=' + value;
                }
            });
            // filter out nulls
            optionStrings = _.filter(optionStrings, _.identity);
            // build license string and return
            return type + ': ' + optionStrings.join(' ');
        },

        setFromString: function(string, options) {
            if (!string) {
                // reset to defaults
                return this.set(this.defaults, options);
            }

            var colonIndex = string.indexOf(':'),
                spaceIndex = string.indexOf(' ');

            // a string without a colon could be a custom license, or a license
            // type without options
            if (colonIndex == -1) {
                if (spaceIndex == -1) {
                    // if there's no space, it's a license type without options
                    return this.set({
                        type: string,
                        options: {},
                        custom: false
                    }, options);
                } else {
                // if there is a space, it's a custom license
                    return this.set({
                        type: null,
                        options: {},
                        custom: string
                    }, options);
                }
            }

            // there is a colon, which indicates a license type with options.
            var type = string.substring(0, colonIndex),
                optionsObj = {},
                optionsString = string.substring(colonIndex + 1);

            _.each(optionsString.split(' '), function(optionString) {
                if (_.isEmpty(optionString)) {
                    return;
                }
                var eqIndex = optionString.indexOf('=');
                if (eqIndex == -1) {
                        // this is a boolean flag
                    optionsObj[optionString] = true;
                } else {
                        // this is a key-value pair
                    var optionKey = optionString.substring(0, eqIndex);
                    var optionVal = optionString.substring(eqIndex + 1);
                    optionsObj[optionKey] = optionVal;
                }
            });

            return this.set({
                type: type, options: optionsObj, custom: false
            }, options);
        }
    });

    return LicenseModel;
});