const DB=require('better-sqlite3');
const {Router}=require('express');

const db=new DB('db.sqlite');
const api=new Router();

const leaderboardSelect='SELECT username, score, length, time, speed FROM leaderboards';
const getLeaderboardsBy={
	score: db.prepare(`${leaderboardSelect} WHERE mode=? ORDER BY score DESC LIMIT ? OFFSET ?`),
	timeA: db.prepare(`${leaderboardSelect} WHERE mode=? ORDER BY time  ASC  LIMIT ? OFFSET ?`),
	timeD: db.prepare(`${leaderboardSelect} WHERE mode=? ORDER BY time  DESC LIMIT ? OFFSET ?`)
};
const addLeaderboard=db.prepare(`
	INSERT
		INTO leaderboards(mode, username, score, length, time, speed)
		VALUES(@mode, @username, @score, @length, @time, @speed)
`);

const levelList=require('./assets/levelList.json');
const validMode=mode => {
	try {
		const [category, name]=mode.split('/');
		return levelList[category].levels.map(l => ''+l).includes(name);
	} catch(e) {
		return false;
	}
};

api.get('/leaderboards/:category/:id', (req, res) => {
	const sort=req.query.sort || 'score';
	if(!['score', 'timeA', 'timeD'].includes(sort)) return res.status(400).json({
		ok: false,
		err: 'Invalid sort'
	});
	const results=+req.query.results || 20;
	if((typeof results)!='number' || results<1 || results >100) return res.status(400).json({
		ok: false,
		err: 'Invalid result count'
	});
	const page=+req.query.page || 1;
	if((typeof page)!='number' || page<1) return res.status(400).json({
		ok: false,
		err: 'Invalid page'
	});

	const data=getLeaderboardsBy[sort]
		.all(req.params.category+'/'+req.params.id, results, (page-1)*results);
	return res.status(200).json({
		ok: true,
		data
	});
});

api.post('/leaderboards/:category/:id', (req, res) => {
	const mode=req.params.category+'/'+req.params.id;
	if((typeof mode)!='string' || !validMode(mode)) return res.status(400).json({
		ok: false,
		err: 'Invalid mode'
	});
	const username=req.body.username;
	if((typeof username)!='string' || username.length>100) return res.status(400).json({
		ok: false,
		err: 'Invalid username'
	});
	const score=req.body.score;
	if((typeof score)!='number' || score%1 || score<0) return res.status(400).json({
		ok: false,
		err: 'Invalid score'
	});
	const length=req.body.length;
	if((typeof length)!='number' || length%1 || length<1) return res.status(400).json({
		ok: false,
		err: 'Invalid length'
	});
	const time=req.body.time;
	if((typeof time)!='number' || time%1 || time<0) return res.status(400).json({
		ok: false,
		err: 'Invalid time'
	});
	const speed=req.body.speed;
	if((typeof speed)!='number' || speed%1 || speed<1) return res.status(400).json({
		ok: false,
		err: 'Invalid speed'
	});

	try {
		addLeaderboard.run({
			mode, username,
			score, length,
			time, speed
		});
		res.json({
			ok: true
		});
	} catch(e) {
		res.status(500).json({
			ok: false,
			err: 'Failed to add score'
		});
	}
});

return module.exports=exports=api;
