'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 {
	fetchScene,
	fetchScenes,
	fetchScenePoster,
} = require('./releases');

const {
	fetchActor,
	fetchActors,
} = require('./actors');

const {
	fetchEntity,
	fetchEntities,
} = require('./entities');

const {
	fetchTag,
	fetchTags,
} = require('./tags');

async 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',
			simpleCollections: 'both',
			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/scenes', fetchScenes);
	router.get('/api/scenes/:releaseId', fetchScene);
	router.get('/api/scenes/:releaseId/poster', fetchScenePoster);

	// router.get('/api/movies', fetchMovies);
	// router.get('/api/movies/:releaseId', fetchMovie);

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

	router.get('/api/entities', async (req, res) => fetchEntities(req, res, null));
	router.get('/api/entities/:entityId', async (req, res) => fetchEntity(req, res, null));

	router.get('/api/channels', async (req, res) => fetchEntities(req, res, 'channel'));
	router.get('/api/channels/:entityId', async (req, res) => fetchEntity(req, res, 'channel'));

	router.get('/api/networks', async (req, res) => fetchEntities(req, res, 'network'));
	router.get('/api/networks/:entityId', async (req, res) => fetchEntity(req, res, 'network'));

	router.get('/api/studios', async (req, res) => fetchEntities(req, res, 'studio'));
	router.get('/api/studios/:entityId', async (req, res) => fetchEntity(req, res, 'studio'));

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

	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;