# Source: api/version.js

    "use strict";

    module.exports = VersionClient;

    /**
     * Used to access Jira REST endpoints in '/rest/api/2/version'
     * @param {JiraClient} jiraClient
     * @constructor VersionClient
     */
    function VersionClient(jiraClient) {
        this.jiraClient = jiraClient;

        /**
         * Creates a version
         *
         * @method createVersion
         * @memberOf VersionClient#
         * @param {Object} opts The request options sent to Jira.
         * @param {Object} opts.version See {@link https://docs.atlassian.com/jira/REST/latest/#d2e3549}
         * @param callback Called when the version has been created.
         */
        this.createVersion = function (opts, callback) {
            var options = {
                uri: this.jiraClient.buildURL('/version'),
                method: 'POST',
                json: true,
                followAllRedirects: true,
                body: opts.version
            };

            this.jiraClient.makeRequest(options, callback);
        };

        /**
         * Modify a version's sequence within a project. The move version bean has 2 alternative field value pairs
         * (opts.position or opts.after).  One and only one of these two must be provided.
         *
         * @method moveVersion
         * @memberOf VersionClient#
         * @param {Object} opts The request options sent to the Jira API.
         * @param {string} opts.versionId The id of the version to move.
         * @param {string} [opts.position] An absolute position, which may have a value of 'First', 'Last', 'Earlier' or
         *     'Later'. Must be provided if opts.after is missing.
         * @param {string} [opts.after] A version to place this version after. The value should be the self link of another
         *     version. Must be provided if opts.position is missing
         * @param callback Called when the version has been moved.
         */
        this.moveVersion = function (opts, callback) {
            var options = this.buildRequestOptions(opts, '/move', 'POST', {position: opts.position, after: opts.after});
            this.jiraClient.makeRequest(options, callback);
        };

        /**
         * Get a project version.
         *
         * @method getVersion
         * @memberOf VersionClient#
         * @param {Object} opts The request options sent to the Jira API.
         * @param {string|number} opts.versionId The id of the version to retrieve.
         * @param callback Called when the version is retrieved.
         */
        this.getVersion = function (opts, callback) {
            var options = this.buildRequestOptions(opts, '', 'GET');
            this.jiraClient.makeRequest(options, callback);
        };

        /**
         * Modify an existing version; any omitted fields will be ignored.
         *
         * @method createVersion
         * @memberOf VersionClient#
         * @param {Object} opts The request options sent to Jira.
         * @param {string} opts.versionId The id of the version to edit.
         * @param {Object} opts.version See {@link https://docs.atlassian.com/jira/REST/latest/#d2e3619}
         * @param callback Called when the version has been modified.
         */
        this.editVersion = function (opts, callback) {
            var options = this.buildRequestOptions(opts, '', 'PUT', opts.version);
            this.jiraClient.makeRequest(options, callback);
        };

        /**
         * Get a bean containing the number of fixed in and affected issues for the given version.
         *
         * @method getRelatedIssueCounts
         * @memberOf VersionClient#
         * @param opts The request options sent to the Jira API.
         * @param opts.versionId The version for which to retrieve related issues.
         * @param callback Called when the count has been retrieved.
         */
        this.getRelatedIssueCounts = function (opts, callback) {
            var options = this.buildRequestOptions(opts, '/relatedIssueCounts', 'GET');
            this.jiraClient.makeRequest(options, callback);
        };

        /**
         * Get the number of unresolved issues for the given version
         *
         * @method getUnresolvedIssueCount
         * @memberOf VersionClient#
         * @param opts The request options sent to the Jira API.
         * @param opts.versionId The version for which to retrieve unresolved issues.
         * @param callback Called when the count has been retrieved.
         */
        this.getUnresolvedIssueCount = function (opts, callback) {
            var options = this.buildRequestOptions(opts, '/unresolvedIssueCount', 'GET');
            this.jiraClient.makeRequest(options, callback);
        };

        /**
         * Get the remote version links associated with the given version id.
         *
         * @method getRemoteLinks
         * @memberOf VersionClient#
         * @param opts The request options sent to the Jira API.
         * @param opts.versionId The version for which to retrieve remote links.
         * @param callback Called when the links have been retrieved.
         */
        this.getRemoteLinks = function (opts, callback) {
            var options = this.buildRequestOptions(opts, '/remotelink', 'GET');
            this.jiraClient.makeRequest(options, callback);
        };

        /**
         * Create a remote version link via POST. The link's global id will be taken from the JSON payload if provided;
         * otherwise, it will be generated.
         *
         * @method createRemoteLink
         * @memberOf VersionClient#
         * @param opts The request options sent to the Jira API.
         * @param opts.versionId The version for which to retrieve unresolved issues.
         * @param opts.remoteLink See {@link https://docs.atlassian.com/jira/REST/latest/#d2e3753}
         * @param callback Called when the remote link has been created.
         */
        this.createRemoteLink = function (opts, callback) {
            var options = this.buildRequestOptions(opts, '/remotelink', 'POST', opts.remoteLink);
            this.jiraClient.makeRequest(options, callback, 'Remotelink Created');
        };

        /**
         * Get a REST sub-resource representing a remote version link.
         *
         * @method getRemoteLinks
         * @memberOf VersionClient#
         * @param opts The request options sent to the Jira API.
         * @param opts.versionId The version for which to retrieve the remote link
         * @param opts.remoteLinkId The global id of the remote link
         * @param callback Called when the link has been retrieved.
         */
        this.getRemoteLink = function (opts, callback) {
            var options = this.buildRequestOptions(opts, '/remotelink/' + opts.remoteLinkId, 'GET');
            this.jiraClient.makeRequest(options, callback);
        };

        /**
         * Delete a remote version link.
         *
         * @method deleteRemoteLink
         * @memberOf VersionClient#
         * @param opts The request options sent to the Jira API.
         * @param opts.versionId The version id
         * @param opts.remoteLinkId The global id of the remote link
         * @param callback Called when the link has been deleted.
         */
        this.deleteRemoteLink = function (opts, callback) {
            var options = this.buildRequestOptions(opts, '/remotelink/' + opts.remoteLinkId, 'DELETE');
            this.jiraClient.makeRequest(options, callback, 'Remote Link Deleted');
        };

        /**
         * Delete a project version.
         *
         * @method deleteVersion
         * @memberOf VersionClient#
         * @param {Object} opts The request options sent to the Jira API.
         * @param {string|number} opts.versionId The id of the version to delete.
         * @param callback Called when the version is deleted.
         */
        this.deleteVersion = function (opts, callback) {
            var options = this.buildRequestOptions(opts, '', 'DELETE');
            this.jiraClient.makeRequest(options, callback, 'Version Deleted');
        };

        /**
         * Delete all remote version links for a given version id.
         *
         * @method deleteAllRemoteLinks
         * @memberOf VersionClient#
         * @param {Object} opts The request options sent to the Jira API.
         * @param {string|number} opts.versionId The id of the version to delete.
         * @param callback Called when the version is deleted.
         */
        this.deleteAllRemoteLinks = function (opts, callback) {
            var options = this.buildRequestOptions(opts, '/remotelink', 'DELETE');
            this.jiraClient.makeRequest(options, callback, 'Remote Links Deleted');
        };

        /**
         * Returns the remote version links for a given global id.
         *
         * @method getGlobalRemoteLink
         * @memberOf VersionClient#
         * @param opts The request options sent to the Jira API.
         * @param opts.globalId The global id of the remote resource that is linked to the versions
         * @param callback Called when the remote link is returned.
         */
        this.getGlobalRemoteLink = function (opts, callback) {
            var options = {
                uri: this.jiraClient.buildURL('/version/remotelink'),
                method: 'GET',
                json: true,
                followAllRedirects: true,
                qs: {globalId: opts.globalId}
            };
            this.jiraClient.makeRequest(options, callback);
        };

        /**
         * Build out the request options necessary to make a particular API call.
         *
         * @private
         * @method buildRequestOptions
         * @memberOf FilterClient#
         * @param {Object} opts The arguments passed to the method.
         * @param {number} opts.versionId The id of the screen to use in the path.
         * @param {Array} [opts.fields] The fields to include
         * @param {Array} [opts.expand] The fields to expand
         * @param {string} path The path of the endpoint following /version/{id}
         * @param {string} method The request method.
         * @param {Object} [body] The request body, if any.
         * @param {Object} [qs] The querystring, if any.  opts.expand and opts.fields arrays will be automagically added.
         * @returns {{uri: string, method: string, body: Object, qs: Object, followAllRedirects: boolean, json: boolean}}
         */
        this.buildRequestOptions = function (opts, path, method, body, qs) {
            var basePath = '/version/' + opts.versionId;
            if (!qs) qs = {};
            if (!body) body = {};

            if (opts.fields) {
                qs.fields = '';
                opts.fields.forEach(function (field) {
                    qs.fields += field + ','
                });
                qs.fields = qs.fields.slice(0, -1);
            }

            if (opts.expand) {
                qs.expand = '';
                opts.expand.forEach(function (ex) {
                    qs.expand += ex + ','
                });
                qs.expand = qs.expand.slice(0, -1);
            }

            return {
                uri: this.jiraClient.buildURL(basePath + path),
                method: method,
                body: body,
                qs: qs,
                followAllRedirects: true,
                json: true
            };
        };
    }