const moment = require('moment-timezone');
const fs = require('fs-extra');
const path = require('path');
const urlService = require('../url');

const errors = require('@tryghost/errors');
const config = require('../../../shared/config');

/**
 * The `routes.yaml` file offers a way to configure your Ghost blog. It's currently a setting feature
 * we have added. That's why the `routes.yaml` file is treated as a "setting" right now.
 * If we want to add single permissions for this file (e.g. upload/download routes.yaml), we can add later.
 *
 * How does it work?
 *
 * - we first reset all url generators (each url generator belongs to one express router)
 *   - we don't destroy the resources, we only release them (this avoids reloading all resources from the db again)
 * - then we reload the whole site app, which will reset all routers and re-create the url generators
 */
const setFromFilePath = (filePath) => {
    const settingsPath = config.getContentPath('settings');
    const backupRoutesPath = path.join(settingsPath, `routes-${moment().format('YYYY-MM-DD-HH-mm-ss')}.yaml`);

    return fs.copy(`${settingsPath}/routes.yaml`, backupRoutesPath)
        .then(() => {
            return fs.copy(filePath, `${settingsPath}/routes.yaml`);
        })
        .then(() => {
            urlService.resetGenerators({releaseResourcesOnly: true});
        })
        .then(() => {
            const siteApp = require('../../../server/web/site/app');

            const bringBackValidRoutes = () => {
                urlService.resetGenerators({releaseResourcesOnly: true});

                return fs.copy(backupRoutesPath, `${settingsPath}/routes.yaml`)
                    .then(() => {
                        return siteApp.reload();
                    });
            };

            try {
                siteApp.reload();
            } catch (err) {
                return bringBackValidRoutes()
                    .finally(() => {
                        throw err;
                    });
            }

            let tries = 0;

            function isBlogRunning() {
                return Promise.delay(1000)
                    .then(() => {
                        if (!urlService.hasFinished()) {
                            if (tries > 5) {
                                throw new errors.InternalServerError({
                                    message: 'Could not load routes.yaml file.'
                                });
                            }

                            tries = tries + 1;
                            return isBlogRunning();
                        }
                    });
            }

            return isBlogRunning()
                .catch((err) => {
                    return bringBackValidRoutes()
                        .finally(() => {
                            throw err;
                        });
                });
        });
};

const get = () => {
    const routesPath = path.join(config.getContentPath('settings'), 'routes.yaml');

    return fs.readFile(routesPath, 'utf-8')
        .catch((err) => {
            if (err.code === 'ENOENT') {
                return Promise.resolve([]);
            }

            if (errors.utils.isIgnitionError(err)) {
                throw err;
            }

            throw new errors.NotFoundError({
                err: err
            });
        });
};

module.exports.setFromFilePath = setFromFilePath;
module.exports.get = get;
