'use strict';

/**
 * Provides state and utility functions for loading and reviewing diffs.
 *
 * Model Attributes:
 *     fileDiffID (number):
 *         The ID of the FileDiff.
 *
 *     file (RB.DiffFile):
 *         Information on the file associated with this diff.
 *
 *     interdiffRevision (number):
 *         The revision on the end of an interdiff range.
 *
 *     interFileDiffID (number):
 *         The ID of the FileDiff on the end of an interdiff range.
 *
 *     revision (number):
 *         The revision of the FileDiff.
 */
RB.DiffReviewable = RB.AbstractReviewable.extend({
    defaults: _.defaults({
        file: null,
        fileDiffID: null,
        interdiffRevision: null,
        interFileDiffID: null,
        revision: null
    }, RB.AbstractReviewable.prototype.defaults),

    commentBlockModel: RB.DiffCommentBlock,
    defaultCommentBlockFields: ['fileDiffID', 'interFileDiffID'],

    /**
     * Load a serialized comment and add comment blocks for it.
     *
     * Args:
     *     serializedCommentBlock (object):
     *         The serialized data for the new comment block(s).
     */
    loadSerializedCommentBlock: function loadSerializedCommentBlock(serializedCommentBlock) {
        this.createCommentBlock({
            reviewRequest: this.get('reviewRequest'),
            review: this.get('review'),
            fileDiffID: this.get('fileDiffID'),
            interFileDiffID: this.get('interFileDiffID'),
            beginLineNum: serializedCommentBlock.linenum,
            endLineNum: serializedCommentBlock.linenum + serializedCommentBlock.num_lines - 1,
            serializedComments: serializedCommentBlock.comments || []
        });
    },


    /**
     * Return the rendered diff for a file.
     *
     * The rendered file will be fetched from the server and eventually
     * returned as the argument to the success callback.
     *
     * Args:
     *     callbacks (object):
     *         The functions used to fetch the corresponding diff fragments.
     *
     *     context (object):
     *         The context passed to each callback function.
     *
     *     options (object, optional):
     *         The option arguments that control the behavior of this function.
     *
     * Option Args:
     *     showDeleted (boolean):
     *         Determines whether or not we want to requeue the corresponding
     *         diff in order to show its deleted content.
     */
    getRenderedDiff: function getRenderedDiff(callbacks, context) {
        var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

        var url = this._buildRenderedDiffURL() + '?index=' + this.get('file').get('index');

        if (options.showDeleted) {
            url += '&show-deleted=1';
        }

        url += '&' + TEMPLATE_SERIAL;

        this._fetchFragment({
            url: url,
            noActivityIndicator: true
        }, callbacks, context);
    },


    /**
     * Return a rendered fragment of a diff.
     *
     * The fragment will be fetched from the server and eventually returned
     * as the argument to the success callback.
     *
     * Args:
     *     options (object):
     *         The option arguments that control the behavior of this function.
     *
     *     callbacks (object):
     *         The functions used to fetch the corresponding diff fragments.
     *
     *     context (object):
     *         The context passed to each callback function.
     *
     * Option Args:
     *     chunkIndex (string):
     *         The chunk index to load.
     */
    getRenderedDiffFragment: function getRenderedDiffFragment(options, callbacks, context) {
        console.assert(options.chunkIndex !== undefined, 'chunkIndex must be provided');

        this._fetchFragment({
            url: this._buildRenderedDiffURL() + 'chunk/' + options.chunkIndex + '/',
            data: {
                'index': this.get('file').get('index'),
                'lines-of-context': options.linesOfContext
            }
        }, callbacks, context);
    },


    /**
     * Fetch the diff fragment from the server.
     *
     * This is used internally by getRenderedDiff and getRenderedDiffFragment
     * to do all the actual fetching and calling of callbacks.
     *
     * Args:
     *     options (object):
     *         The option arguments that control the behavior of this function.
     *
     *     callbacks (object):
     *         The functions used to fetch the corresponding diff fragments.
     *
     *     context (object):
     *         The context passed to each callback function.
     */
    _fetchFragment: function _fetchFragment(options, callbacks, context) {
        RB.apiCall(_.defaults({
            type: 'GET',
            dataType: 'html'
        }, options, _.bindCallbacks(callbacks, context)));
    },


    /**
     * Return a URL that forms the base of a diff fragment fetch.
     *
     * Returns:
     *     string:
     *     The URL for fetching diff fragments.
     */
    _buildRenderedDiffURL: function _buildRenderedDiffURL() {
        var interdiffRevision = this.get('interdiffRevision');
        var interFileDiffID = this.get('interFileDiffID');
        var revisionStr = this.get('revision');

        if (interdiffRevision) {
            revisionStr += '-' + interdiffRevision;
        }

        return this.get('reviewRequest').get('reviewURL') + 'diff/' + revisionStr + '/fragment/' + this.get('fileDiffID') + (interFileDiffID ? '-' + interFileDiffID : '') + '/';
    }
});

//# sourceMappingURL=diffReviewableModel.js.map