'use strict';

var q = require("q");
var MongoClient = require('mongodb').MongoClient;
var connectionURL = require('./MongoURL');
var ServerConstants = require('../../../constants/ServerConstants');
var logger = require('../../../utils/Logger').loggers.get('db');
var dbConfig = require('../DatabaseConfig');

var connectedDBs = {};

module.exports = {
    initialise: async function (connectionName, dbCloseCallBack) {
        connectionName = dbConfig.validateConnectionName(connectionName);
        const url = connectionURL(connectionName);
        try{
            const client = await MongoClient.connect(url, { useNewUrlParser: true });
            connectedDBs[connectionName] = {};
            connectedDBs[connectionName].client = client;
            connectedDBs[connectionName].db = client.db();
            connectedDBs[connectionName].db.on('close', function (reason) {
                logger.error('mongodb connection is closed. reason is ' + reason);
                delete connectedDBs[connectionName];
                if (dbCloseCallBack && typeof dbCloseCallBack === 'function'){
                    dbCloseCallBack(connectionName);
                }
            });

        }catch (err) {
            const errorMsg = "Error connecting to Mongodb: " + err;
            logger.error(errorMsg);
            logger.error(err);
            throw new Error(errorMsg);
        }
    },

    close: function(connectionName) {
        var deferred = q.defer();

        connectionName = dbConfig.validateConnectionName(connectionName);

        // this should only be called on application end. The connections should not be closed each time because they are pooled
        // so they don't have to be opened for each operation
        if (connectedDBs[connectionName] && connectedDBs[connectionName].client) {
            connectedDBs[connectionName].client.close(function (err) {
                delete connectedDBs[connectionName];
                if (err) {
                    deferred.reject(new Error("Error closing Mongo database: " + err));
                } else {
                    deferred.resolve("Closed Mongo database");
                }
            });
        } else {
            deferred.reject(new Error("Mongo database already closed on call of MongoConnection.close"));
        }

        return deferred.promise;
    },

    getDatabase: function(connectionName) {
        connectionName = dbConfig.validateConnectionName(connectionName);

        return connectedDBs[connectionName].db;
    },

    getCollection: function (callback, connectionName ) {
        connectionName = dbConfig.validateConnectionName(connectionName);
        if (!connectedDBs[connectionName] || !connectedDBs[connectionName].db) {
            callback(new Error("Database connection not initialised"));
        } else {
            if (connectedDBs[connectionName].collection){
                callback(null, connectedDBs[connectionName].collection);
            }
            else{
                const mongo = dbConfig.getDataServicesConfig(connectionName);
                let collectionName = mongo.collection ? mongo.collection : ServerConstants.MONGO_COLLECTION_NAME;
                connectedDBs[connectionName].db.collection(collectionName,
                    function (err, collection) {
                        if (err) {
                            var errorMsg = "Error creating collection : " + err;
                            callback(errorMsg);
                        } else {
                            connectedDBs[connectionName].collection = collection;
                            callback(null, collection);
                        }
                    });
            }
        }
    }
};
