<commit_before>define(
function (require) {
	var Backbone = require('backbone'),
        sources = require('streamhub-backbone/const/sources'),
        types = require('streamhub-backbone/const/types'),
        transformers = require('streamhub-backbone/const/transformers');

/** @lends Content */
var Content = Backbone.Model.extend(
/** @lends Content.prototype */
{
    /**
    Stuff a user might want to look at.
    Content may be sourced from another Collection that lives in StreamHub's Cloud.
    When this is the case, Content is instantiated with json like this https://gist.github.com/4527966
    Otherwise, it can be passed a string of bodyHtml (WIP)

    @class Content
    @constructs
    @augments Backbone.Model
    @param {Object} props - Properties that should be .set on the Content Model. Backbone style.
    @param {string} props.id - The ID of the Content in StreamHub
    @param {Number} props.event - The ID of the event in StreamHub spacetime
    @param {string} props.bodyHtml - An HTML snippet for the main textual part of the Content
    @param {string} props.authorId - The ID of the Author in StreamHub
    @param {Object} props.author - Hydrated author data, if you have it handy
    @param {oEmbed[]} props.attachments - Attached media to display with the Content
    @param {Number} props.createdAt - Unix timestamp of when the Content was originally created
    @param {Number} props.updatedAt - Unix timestamp of when the Content was updated (perhaps edited)
    @param {string} props.replaces - ID of the Content that this Content should replace in displays (perhaps because of an edit)
    @param {string} props.parentId - ID of the parent Content
    @param {Number} props.source - Enum of the Content source. See `const/sources`
    @param {Number} props.type - Enum of the sdkData state type. See `const/types`
    */
    constructor: function (htmlOrObj) {
        var attrs = {};
        // Allow passing HTML string as only param (#TODO demo)
        if (typeof(htmlOrObj)==='object') {
            attrs = htmlOrObj;
        } else {
            attrs.bodyHtml = htmlOrObj;
        }
        Backbone.Model.prototype.constructor.call(this, attrs);
    },
    /** Runs when constructing too.
    This is the usual initialize method most Backbone Models should use **/
	initialize: function (attrs) {
	}
});

/**
Create a piece of Content from the JS sdkData 'state' response format
*/
Content.fromSdk = function (d) {
    var c = d.content,
        attrs,
        attachments = _getAttachmentsFromState(d);

    // Don't create Content for nonvisible items
    // @todo Create one still, but with no vis. There may be children that still need to
    // be anchored to the right thing.
    if (d.vis !== 1) {
        return null;
    }

    // pluck information from sdkData in just the right way
    // @todo see if content id is in different place in stream and bootstrap data
    attrs = {
        id: c.id ,
        event: d.event,
        bodyHtml: formatBodyHtml(c.bodyHtml),
        ancestorId: c.ancestorId,
        annotations: c.annotations,
        authorId: c.authorId,
        createdAt: c.createdAt,
        updatedAt: c.updatedAt,
        replaces: c.replaces || null,
        parentId: c.parentId || null,
        source: d.source,
        transport: d.transport,
        type: d.type,
        vis: d.vis,
        feedEntry: c.feedEntry || null
    };
    if (c.author) {
        attrs.author = c.author;
    }
    if (attachments) {
        attrs.attachments = attachments;
    }
    return new Content(attrs);

    function formatBodyHtml (bodyHtml) {
        // wrap in <p> if not already
        if (bodyHtml.substr(0,1)!=='<') {
            return '<p>'+bodyHtml+'</p>';
        }
        return bodyHtml
    }
};

/**
Content models themselves can handle SdkState information
that is relevant to them. That way the Content can emit it's
own `reply` and `like` events and stuff
@TODO make actual `reply` events 'and stuff'
*/
Content.prototype._handleSdkState = function (s) {
    if (s.type==types.OEMBED) this._handleSdkOembedState(s);
};
/**
Handle streaming attachments
*/
Content.prototype._handleSdkOembedState = function (s) {
    var newAttachments = _getAttachmentsFromState(s),
        oldAttachments = this.get('attachments') || [];
    for (var i = 0; i < oldAttachments.length; i++) {
        if (newAttachments && oldAttachments[i].url === newAttachments[0].url) {
            newAttachments = null;
        }
    }
    if (newAttachments) {
        this.set('attachments', oldAttachments.concat(newAttachments));
    }
};

/**
There may be information that could lead to an attachment representation
hiding in the sdkData state. This plucks them out in the case of an RSS Image feed
But I think those might now come down as types.OEMBED states
@private
@todo Grab more attachments, or test to see if this is necessary now
*/
function _getAttachmentsFromState (s) {
    // Only do this for RSS for now<commit_msg>Add TODO and comment to new attachments logic<commit_after>define(
function (require) {
	var Backbone = require('backbone'),
        sources = require('streamhub-backbone/const/sources'),
        types = require('streamhub-backbone/const/types'),
        transformers = require('streamhub-backbone/const/transformers');

/** @lends Content */
var Content = Backbone.Model.extend(
/** @lends Content.prototype */
{
    /**
    Stuff a user might want to look at.
    Content may be sourced from another Collection that lives in StreamHub's Cloud.
    When this is the case, Content is instantiated with json like this https://gist.github.com/4527966
    Otherwise, it can be passed a string of bodyHtml (WIP)

    @class Content
    @constructs
    @augments Backbone.Model
    @param {Object} props - Properties that should be .set on the Content Model. Backbone style.
    @param {string} props.id - The ID of the Content in StreamHub
    @param {Number} props.event - The ID of the event in StreamHub spacetime
    @param {string} props.bodyHtml - An HTML snippet for the main textual part of the Content
    @param {string} props.authorId - The ID of the Author in StreamHub
    @param {Object} props.author - Hydrated author data, if you have it handy
    @param {oEmbed[]} props.attachments - Attached media to display with the Content
    @param {Number} props.createdAt - Unix timestamp of when the Content was originally created
    @param {Number} props.updatedAt - Unix timestamp of when the Content was updated (perhaps edited)
    @param {string} props.replaces - ID of the Content that this Content should replace in displays (perhaps because of an edit)
    @param {string} props.parentId - ID of the parent Content
    @param {Number} props.source - Enum of the Content source. See `const/sources`
    @param {Number} props.type - Enum of the sdkData state type. See `const/types`
    */
    constructor: function (htmlOrObj) {
        var attrs = {};
        // Allow passing HTML string as only param (#TODO demo)
        if (typeof(htmlOrObj)==='object') {
            attrs = htmlOrObj;
        } else {
            attrs.bodyHtml = htmlOrObj;
        }
        Backbone.Model.prototype.constructor.call(this, attrs);
    },
    /** Runs when constructing too.
    This is the usual initialize method most Backbone Models should use **/
	initialize: function (attrs) {
	}
});

/**
Create a piece of Content from the JS sdkData 'state' response format
*/
Content.fromSdk = function (d) {
    var c = d.content,
        attrs,
        attachments = _getAttachmentsFromState(d);

    // Don't create Content for nonvisible items
    // @todo Create one still, but with no vis. There may be children that still need to
    // be anchored to the right thing.
    if (d.vis !== 1) {
        return null;
    }

    // pluck information from sdkData in just the right way
    // @todo see if content id is in different place in stream and bootstrap data
    attrs = {
        id: c.id ,
        event: d.event,
        bodyHtml: formatBodyHtml(c.bodyHtml),
        ancestorId: c.ancestorId,
        annotations: c.annotations,
        authorId: c.authorId,
        createdAt: c.createdAt,
        updatedAt: c.updatedAt,
        replaces: c.replaces || null,
        parentId: c.parentId || null,
        source: d.source,
        transport: d.transport,
        type: d.type,
        vis: d.vis,
        feedEntry: c.feedEntry || null
    };
    if (c.author) {
        attrs.author = c.author;
    }
    if (attachments) {
        attrs.attachments = attachments;
    }
    return new Content(attrs);

    function formatBodyHtml (bodyHtml) {
        // wrap in <p> if not already
        if (bodyHtml.substr(0,1)!=='<') {
            return '<p>'+bodyHtml+'</p>';
        }
        return bodyHtml
    }
};

/**
Content models themselves can handle SdkState information
that is relevant to them. That way the Content can emit it's
own `reply` and `like` events and stuff
@TODO make actual `reply` events 'and stuff'
*/
Content.prototype._handleSdkState = function (s) {
    if (s.type==types.OEMBED) this._handleSdkOembedState(s);
};
/**
Handle streaming attachments
*/
Content.prototype._handleSdkOembedState = function (s) {
    var newAttachments = _getAttachmentsFromState(s),
        oldAttachments = this.get('attachments') || [];
    for (var i = 0; i < oldAttachments.length; i++) {
        // This assumes that newAttachments.length always === 1
        // TODO: Audit this logic, make sure it works when
        // newAttachments.length > 1
        if (newAttachments && oldAttachments[i].url === newAttachments[0].url) {
            newAttachments = null;
        }
    }
    if (newAttachments) {
        this.set('attachments', oldAttachments.concat(newAttachments));
    }
};

/**
There may be information that could lead to an attachment representation
hiding in the sdkData state. This plucks them out in the case of an RSS Image feed
But I think those might now come down as types.OEMBED states
@private
@todo Grab more attachments, or test to see if this is necessary now
*/
function _getAttachmentsFromState (s) {
    // Only do this for RSS for now
{'fraction_non_alphanumeric': 0.09828975820719481, 'fraction_numerical': 0.002555533713387065, 'mean_word_length': 2.7713120830244624, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 10, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2710301', 'n_tokens_mistral': 2966, 'n_tokens_neox': 2892, 'n_words': 1079}