/*Canopy - The next generation of stoner streaming software
Copyright (C) 2024  Rainbownapkin and the TTN Community

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.*/

//Define NPM imports
const express = require('express');
const session = require('express-session');
const {createServer } = require('http');
const { Server } = require('socket.io');
const path = require('path');
const mongoStore = require('connect-mongo');
const mongoose = require('mongoose');

//Define Local Imports
const channelManager = require('./app/channel/channelManager');
const scheduler = require('./utils/scheduler');
const statModel = require('./schemas/statSchema');
const flairModel = require('./schemas/flairSchema');
const emoteModel = require('./schemas/emoteSchema');
const tokeCommandModel = require('./schemas/tokebot/tokeCommandSchema');
const indexRouter = require('./routers/indexRouter');
const registerRouter = require('./routers/registerRouter');
const profileRouter = require('./routers/profileRouter');
const adminPanelRouter = require('./routers/adminPanelRouter');
const channelRouter = require('./routers/channelRouter');
const newChannelRouter = require('./routers/newChannelRouter');
const panelRouter = require('./routers/panelRouter');
const popupRouter = require('./routers/popupRouter');
const apiRouter = require('./routers/apiRouter');

//Define Config
const config = require('../config.json');
const port = config.port;
const dbUrl = `mongodb://${config.db.user}:${config.db.pass}@${config.db.address}:${config.db.port}/${config.db.database}`;

//Define Node JS
const app = express();

//Define session-store (exported so we can kill sessions from user schema)
module.exports.store = mongoStore.create({mongoUrl: dbUrl});

//define sessionMiddleware
const sessionMiddleware = session({
    secret: config.sessionSecret,
    resave: false,
    saveUninitialized: false,
    store: module.exports.store 
});

//Define http and socket.io servers
const httpServer = createServer(app);
const io = new Server(httpServer, {});

//Connect mongoose to the database
mongoose.set("sanitizeFilter", true).connect(dbUrl).then(() => {
    console.log("Connected to DB");
}).catch((err) => {
    console.error("Unable to connecto to DB: ");
    console.error(err);
    process.exit();
});

//Set View Engine
app.set('view engine', 'ejs');
app.set('views', __dirname + '/views');

//Middlware
//Enable Express
app.use(express.json());

//Enable Express-Sessions
app.use(sessionMiddleware);

//Enable Express-Session w/ Socket.IO
io.engine.use(sessionMiddleware);

//Routes
//Humie-Friendly
app.use('/', indexRouter);
app.use('/register', registerRouter);
app.use('/profile', profileRouter);
app.use('/adminPanel', adminPanelRouter);
app.use('/c', channelRouter);
app.use('/newChannel', newChannelRouter);
//Panel
app.use('/panel', panelRouter);
//Popup
app.use('/popup', popupRouter);
//Bot-Ready
app.use('/api', apiRouter);

//3rd-Party Browser-Side Libraries
app.use('/lib/bootstrap-icons',express.static(path.join(__dirname, '../node_modules/bootstrap-icons')));
app.use('/lib/socket.io',express.static(path.join(__dirname, '../node_modules/socket.io/client-dist')));
app.use('/lib/validator',express.static(path.join(__dirname, '../node_modules/validator')));

//Static File Server
app.use(express.static(path.join(__dirname, '../www')));

//Increment launch counter
statModel.incrementLaunchCount();

//Load default flairs
flairModel.loadDefaults();

//Load default emots
emoteModel.loadDefaults();

//Load default toke commands
tokeCommandModel.loadDefaults();

//Kick off scheduled-jobs
scheduler.kickoff();

//Hand over general-namespace socket.io connections to the channel manager
module.exports.channelManager = new channelManager(io)

//Listen Function
httpServer.listen(port, () => {
    console.log(`Opening port ${port}`);
});