'use strict';

const path = require('path');
const config = require('config');
const express = require('express');
const { postgraphile } = require('postgraphile');
const Router = require('express-promise-router');
const bodyParser = require('body-parser');

const PgConnectionFilterPlugin = require('postgraphile-plugin-connection-filter');
const PgSimplifyInflectorPlugin = require('@graphile-contrib/pg-simplify-inflector');
const PgOrderByRelatedPlugin = require('@graphile-contrib/pg-order-by-related');

const logger = require('../logger')(__filename);
const { ActorPlugins, SitePlugins, ReleasePlugins } = require('./plugins/plugins');

const {
    fetchReleases,
    fetchReleaseById,
    fetchActorReleases,
    fetchNetworkReleases,
    fetchSiteReleases,
    fetchTagReleases,
} = require('./releases');

const {
    fetchNetworks,
    fetchNetworksFromReleases,
} = require('./networks');

const { fetchActors } = require('./actors');
const { fetchSites } = require('./sites');
const { fetchTags } = require('./tags');

function initServer() {
    const app = express();
    const router = Router();

    const connectionString = `postgres://${config.database.user}:${config.database.password}@${config.database.host}:5432/${config.database.database}`;

    app.use(postgraphile(
        connectionString,
        'public',
        {
            // watchPg: true,
            dynamicJson: true,
            graphiql: true,
            enhanceGraphiql: true,
            allowExplain: () => true,
            simpleCollections: 'only',
            graphileBuildOptions: {
                pgOmitListSuffix: true,
                connectionFilterRelations: true,
            },
            appendPlugins: [
                PgSimplifyInflectorPlugin,
                PgConnectionFilterPlugin,
                PgOrderByRelatedPlugin,
                ...ActorPlugins,
                ...SitePlugins,
                ...ReleasePlugins,
            ],
        },
    ));

    app.set('view engine', 'ejs');

    router.use('/media', express.static(config.media.path));
    router.use(express.static('public'));

    router.use('/img', (req, res) => {
        res.status(404).send();
    });

    router.use(bodyParser.json({ strict: false }));

    router.get('/api/releases', fetchReleases);
    router.get('/api/releases/:releaseId', fetchReleaseById);
    router.get('/api/releases/networks', fetchNetworksFromReleases);

    router.get('/api/actors', fetchActors);
    router.get('/api/actors/:actorId', fetchActors);
    router.get('/api/actors/:actorId/releases', fetchActorReleases);

    router.get('/api/networks', fetchNetworks);
    router.get('/api/networks/:networkId', fetchNetworks);
    router.get('/api/networks/:networkId/releases', fetchNetworkReleases);

    router.get('/api/sites', fetchSites);
    router.get('/api/sites/:siteId', fetchSites);
    router.get('/api/sites/:siteId/releases', fetchSiteReleases);

    router.get('/api/tags', fetchTags);
    router.get('/api/tags/:tagId', fetchTags);
    router.get('/api/tags/:tagId/releases', fetchTagReleases);

    router.get('*', (req, res) => {
        res.render(path.join(__dirname, '../../assets/index.ejs'), {
            env: JSON.stringify({
                sfw: !!req.headers.sfw || Object.prototype.hasOwnProperty.call(req.query, 'sfw'),
            }),
        });
    });

    app.use(router);

    const server = app.listen(config.web.port, config.web.host, () => {
        const { address, port } = server.address();

        logger.info(`Web server listening on ${address}:${port}`);
    });
}

module.exports = initServer;