// coordinator
// http
const http = require('http')
// filesystem
const fs = require('fs')
// server config
const config = require('./config.json')
// node date time
const node_time = require('node-datetime')

const mongodb_client = require('./mongodb_client.js')

const crypto = require('crypto')

var querystring = require('querystring')

// write startup server history
var logs_dir = './logs'
if (!fs.existsSync(logs_dir))
    fs.mkdirSync(logs_dir)

fs.appendFileSync(`./${logs_dir}/launch_history.log`, (node_time.create().format('Y-m-d H:M:S')).toString() + '\n')


async function PostSessionServer(data, ip, port, callback) {
    // Build the post string from an object
    // An object of options to indicate where to post to
    var post_options = {
        host: ip,
        port: port,
        method: 'POST',
        headers: {
            'Content-Type': 'applicaiton/json',
            'Content-Length': Buffer.byteLength(data)
        }
    }
      
    // Set up the request
    var post_req = http.request(post_options, function(res) {
        res.setEncoding('utf8')
        res.on('data', async function (answer) {
            callback(answer)
        })
    })

    // post the data
    post_req.write(data)
    post_req.end()
}

// response function
async function create_response(request, callback) {
    var mongo_client = new mongodb_client(config.mongodb_url)
    var database = await mongo_client.connect_database(config.database_name)

    var response = ''
    try {
        if (request.verb == 'GET_TITLES') {
            var title = database.collection('title')
            response = await title.find().skip(request.start).limit(request.count).toArray()
            response = JSON.stringify(response)
            callback(response)

        } else if (request.verb == 'PLAN_SESSION') {
            var session_sheduled = database.collection('session_sheduled')
            var sessions = await session_sheduled.find().toArray()
            
        } else if (request.verb == 'CREATE_SESSION') {
            
            var session_server = database.collection('session_server')
            var servers = await session_server.find({'title':request.title}).toArray()
            
            if (!servers.length) {
                response = '{"msg":"SERVERS_NOT_FOUND"}'
                callback(response)
            }
            // find free server and create session
            var session_active = database.collection('session_active')

            // find free server
            var free_server
            var servers_length = servers.length
            for (var i = 0; i < servers_length; ++i) {
                var sessions = await session_active.find({'server_id':servers[i].server_id}).toArray()
                if (servers[i].limit > sessions.length) {
                    free_server = servers[i]
                    break
                }
            }
            if (free_server == null) {
                response = '{"msg":"SESSION_LIMIT_REACHED"}'
                callback(response)
            }

            PostSessionServer(`{"verb":"CREATE_SESSION", "title":"${request.title}"}`, free_server.ip, free_server.port, async function(answer) {
                var json_answer = JSON.parse(answer)
                // add session to database
                await session_active.insertOne({
                    server_id:free_server.server_id,
                    link:json_answer.link
                })
                response = `{"msg":"SESSION_CREATED", "link":"${json_answer.link}"}`
                callback(response)
            })

        } else if (request.verb == 'CONNECT_SESSION') {
            callback(response)
        } else {
            response = '{"msg":"UNKNOWN_VERB"}'
            callback(response)
        }
    }
    catch(e) {
        console.error(e)
    }
}


// start http server
const server = http.createServer(function(request, response) {
    if (request.method == 'POST') {
        var body = ''
        
        request.on('data', function(data) {
            body += data
        })

        request.on('end', function() {
            response.writeHead(200, {'Content-Type': 'message'})
            try {
                create_response(JSON.parse(body), function(message) {
                    response.end(message)
                })
            }
            catch(e) {
                console.error(e)
            }
            console.log('received: "', body, '"')
        })
    }
    else {
        var message = 'UNDEFINED_REQUEST' + ': ' + request.method.toString()
        response.writeHead(200, {'Content-Type': 'message'})
        response.end(message)
        console.log(message)
    }
})

server.listen(config.port, config.ip)
console.log(`Listening at http://${config.ip}:${config.port}`)