const debug = require('@tryghost/debug')('routing:taxonomy-router');
const config = require('../../../shared/config');
const ParentRouter = require('./parent-router');
const RSSRouter = require('./rss-router');
const urlUtils = require('../../../shared/url-utils');
const controllers = require('./controllers');
const middleware = require('./middleware');

/**
 * @description Taxonomies are groupings of posts based on a common relation.
 * Taxonomies do not change the url of a resource.
 */
class TaxonomyRouter extends ParentRouter {
    constructor(key, permalinks, RESOURCE_CONFIG, routerCreated) {
        super('Taxonomy');

        this.taxonomyKey = key;
        this.RESOURCE_CONFIG = RESOURCE_CONFIG;

        this.permalinks = {
            value: permalinks
        };

        this.permalinks.getValue = () => {
            return this.permalinks.value;
        };

        this.routerCreated = routerCreated;

        debug(this.permalinks);

        this._registerRoutes();
    }

    /**
     * @description Register all routes of this router.
     * @private
     */
    _registerRoutes() {
        // REGISTER: context middleware
        this.router().use(this._prepareContext.bind(this));

        // REGISTER: redirects across routers
        this.router().param('slug', this._respectDominantRouter.bind(this));

        // REGISTER: enable rss by default
        this.rssRouter = new RSSRouter();
        this.mountRouter(this.permalinks.getValue(), this.rssRouter.router());

        // REGISTER: e.g. /tag/:slug/
        this.mountRoute(this.permalinks.getValue(), controllers.channel);

        // REGISTER: enable pagination for each taxonomy by default
        this.router().param('page', middleware.pageParam);
        this.mountRoute(urlUtils.urlJoin(this.permalinks.value, 'page', ':page(\\d+)'), controllers.channel);

        // REGISTER: edit redirect to admin client e.g. /tag/:slug/edit
        if (config.get('admin:redirects')) {
            this.mountRoute(urlUtils.urlJoin(this.permalinks.value, 'edit'), this._redirectEditOption.bind(this));
        }

        this.routerCreated(this);
    }

    /**
     * @description Prepare context for routing middleware/controllers.
     * @param {Object} req
     * @param {Object} res
     * @param {Function} next
     * @private
     */
    _prepareContext(req, res, next) {
        res.routerOptions = {
            type: 'channel',
            name: this.taxonomyKey,
            permalinks: this.permalinks.getValue(),
            data: {[this.taxonomyKey]: this.RESOURCE_CONFIG.QUERY[this.taxonomyKey]},
            filter: this.RESOURCE_CONFIG.TAXONOMIES[this.taxonomyKey].filter,
            resourceType: this.getResourceType(),
            context: [this.taxonomyKey],
            slugTemplate: true,
            identifier: this.identifier
        };

        next();
    }

    /**
     * @description Simple controller function to redirect /edit to admin client
     * @param {Object} req
     * @param {Object} res
     * @private
     */
    _redirectEditOption(req, res) {
        urlUtils.redirectToAdmin(302, res, this.RESOURCE_CONFIG.TAXONOMIES[this.taxonomyKey].editRedirect.replace(':slug', req.params.slug));
    }

    /**
     * @description Get resource type e.g. tags or authors
     * @returns {*}
     */
    getResourceType() {
        return this.RESOURCE_CONFIG.TAXONOMIES[this.taxonomyKey].resource;
    }

    /**
     * @description There is no default/index route for taxonomies e.g. /tag/ does not exist, only /tag/:slug/
     * @returns {null}
     */
    getRoute() {
        return null;
    }
}

module.exports = TaxonomyRouter;
