define('bitbucket/internal/feature/readme/common', [
    'jquery',
    'lib/jsuri',
    'lodash',
    'bitbucket/util/navbuilder',
    'bitbucket/internal/model/page-state',
    'bitbucket/internal/util/text',
    'exports'
], function (
    $,
    Uri,
    _,
    nav,
    pageState,
    text,
    exports
) {

    /**
     * Correctly append a query parameter, either with '?' or '&' depending on the url.
     *
     * Ideally we would use jsuri but it plays silly buggers with paths without an folders
     *
     * @param {string} url - url to append parameters to
     * @param {string} key - the query parameter name
     * @param {string} value - the query parameter value
     * @returns {string} new url containing the additional query parameter
     */
    function appendQueryParam(url, key, value) {
        var fragment = '';
        var fragmentIndex = url.indexOf('#');
        if (fragmentIndex !== -1) {
            fragment = url.substr(fragmentIndex);
            url = url.substr(0, fragmentIndex);
        }
        return url + (url.indexOf('?') !== -1 ? '&' : '?') + encodeURIComponent(key) + '=' + encodeURIComponent(value) + fragment;
    }

    /**
     * Creates the relevant REST URL for a readme file at given revision.
     * Passes the file contentId purely for browser caching.
     *
     * eg.
     * /markup/latest/projects/PROJECT_1/repos/rep_1/markup/somedir/README.md?at=master
     */
    exports.createUrl = function createUrl(path, revision, contentId) {
        var params = $.extend({}, {
            blob:contentId,
            at:revision
        });
        return nav.newBuilder([
            'rest', 'readme', 'latest', 'projects', pageState.getProject().getKey(), 'repos', pageState.getRepository().getSlug(), 'markup'
        ].concat(path)).withParams(params).build();
    };

    /**
     * Update all of the {@code a} and {@code img} links with '?at=branch' to allow users to stay within the current context.
     * @param {jQuery} $content - element to search for links within
     * @param {string=} dir     - optional parameter for {@link #_appendAtIfRelative}
     * @returns {jQuery} the same {@code $content}
     */
    exports.updateLinks = function($content, dir) {
        function updateAll(tag, attr, process) {
            $content.find(tag).each(function() {
                $(this).attr(attr, exports._appendAtIfRelative($(this).attr(attr), pageState.getRevisionRef().getId(), dir, process));
            });
        }

        updateAll('a', 'href');

        updateAll('img', 'src', function(link) {
            // For images always append the 'raw' query parameter to ensure Stash displays it correctly
            return (new Uri(link).getQueryParamValues('raw').length === 0) ? appendQueryParam(link, 'raw', '') : link;
        });
        return $content;
    };

    /**
     *
     * This method will not append to absolute links, or links that are only a #fragment reference.
     *
     * @param {string} link - URL to update
     * @param {string} at   - current ref
     * @param {string=} dir - optional path, most likely {@code window.location.pathname}
     * @param {Function=} process - optional function to process relative links
     * @returns {string} potentially updated URL
     * @private
     */
    exports._appendAtIfRelative = function(link, at, dir, process) {
        // Don't touch absolute URIs ("mailto:...", "http:...", etc), or #fragment links
        if (link && !text.isUriAbsolute(link) && !_.startsWith(link, '#')) {
            // If we're viewing from '/browse' then the relative paths will be wrong
            // Don't append dir if link starts with '/' - should be relative to host
            if (dir && !_.endsWith(dir, '/') && !_.startsWith(link, '/')) {
                link = dir + '/' + link;
            }

            // Don't bother searching if we're on the default ref
            if (!pageState.getRevisionRef().isDefault()) {
                link = appendQueryParam(link, 'at', at);
            }

            link = process ? process(link) : link;
        }
        return link;
    };

    exports.DATA = $.Deferred();
    _PageDataPlugin.ready('com.atlassian.bitbucket.server.bitbucket-readme:readme-provider', 'bitbucket.layout.repository', function(value) {
        exports.DATA.resolve(value);
    });

});
