'use strict'

var VError = require('verror')

class DbConnector {
  constructor(){
    this._connPromises = null
    this._mongooseDbName = null
    this._options = null
    this._mongoDbNames = null
  }

  // TODO: check every config has a name
  init(configs, options){
    this._options = options
    this._connPromises = []
    this._mongoDbNames = []

    var configsOk = configs.every((x) => {
      return typeof x.name == 'string' || Array.isArray(x.name)
    })
    if (!configsOk)
      throw new VError('DB configurations must provide a name')

    // find mongoose connection
    var mongooseIdx = configs.findIndex((x) => {return x.mongoose === true})
    if (mongooseIdx >= 0){
      let mongooseConfig = configs.splice(mongooseIdx, 1)[0] // get mongoose config and remove it from array
      this._connectMongoose(mongooseConfig)
    }

    // find & connect to mongo DBs
    var mongoConfigs = configs.filter((x) => {return x.connectionString.startsWith('mongodb://')})
    if (mongoConfigs.length > 0){
      let mongoclient = require('mongodb').MongoClient
      for (let cfg of mongoConfigs){
        this._connectMongo(cfg, mongoclient)
      }
    }
    //
    // // find mysql configs
    // var mysqlConfigs = configs.filter((x) => {return x.connectionString.startsWith('mysql://')})
    // this._connectMysql(mysqlConfigs)
    //
    // // find postgresql configs
    // var pgConfigs = configs.filter((x) => {return x.connectionString.startsWith('postgresql://')})
    // this._coonectPostgresql(pgConfigs)

    return Promise.all(this._connPromises)
  }

  // close all connections
  close(){
    this._closePromises = [
      this._closeMongoose()
    ]
    this._closeMongos()
    return Promise.all(this._closePromises)
  }

  // connect using Mongoose
  _connectMongoose(config){
    if (this._options == null || this._options.mongoose == null)
      throw new VError('Mongoose object must be provided')

    this._options.mongoose.Promise = global.Promise // tells mongoose to use native Promise
    this._options.mongoose.connect(config.connectionString, { mongos: config.multi || false })
    var mongoosedb = this._options.mongoose.connection
    this._mongooseDbName = config.name
    this._connPromises.push(new Promise((resolve, reject) => {

      // custom timeout when mongoose doesn't raise an error at all
      let tm = setTimeout(() => {
        reject(new VError(`Mongoose/${this._mongooseDbName} connection error`))
      }, 60 * 1000) // 1 minute

      mongoosedb.on('error', (err) => {
        clearTimeout(tm)
        reject(new VError(err, `Mongoose/${self._mongooseDbName} connection error`))
      })

      mongoosedb.once('open', () => {
        clearTimeout(tm)
        console.log(`Mongoose/${self._mongooseDbName} connection OK`)
        resolve()
      })
    }))
  }

  // connecto to Mongo using native driver
  _connectMongo(config, mongoclient){
    this._connPromises.push(new Promise((resolve, reject) => {
      mongoclient.connect(config.connectionString, (err, db)=>{
        if (err != null)
          return reject(new VError(err, `Mongo/${config.name} connection error`))

        this[config.name] = db // add connection object to the class
        this._mongoDbNames.push(config.name)
        console.log(`Mongo/${config.name} connection ok`)
        resolve()
      })
    }))
  }

  // close mongoose connection
  _closeMongoose(){
    if (this._mongooseDbName == null)
      return Promise.resolve()

    return new Promise((resolve, reject) =>{
      this._options.mongoose.disconnect((err) => {
        if (err != null)
          console.log(`Mongoose/${this._mongooseDbName} connection close error`)
        else
          console.log(`Mongoose/${this._mongooseDbName} connection closed`)
        resolve()
      })
    })
  }

  //  close all native mongos connections
  _closeMongos(){
    for (let dbName of this._mongoDbNames){
      if (this[dbName] == null)
        continue

      this._closePromises.push(new Promise((resolve, reject)=>{
        this[dbName].close((err)=>{
          if (err != null)
            console.log(`Mongo/${dbname} connection close error`)
          else
            console.log(`Mongo/${dbName} connection closed`)
          resolve()
        })
      }))
    }
  }

}

const self = module.exports = exports = new DbConnector()

@@ -82,35 +82,30 @@
 %7B%0A    this._
-connPromise
+option
 s = null%0A   
@@ -137,33 +137,8 @@
 ull%0A
-    this._options = null%0A
     
@@ -172,49 +172,8 @@
  %7D%0A%0A
-  // TODO: check every config has a name%0A
   in
@@ -250,16 +250,16 @@
 es = %5B%5D%0A
+
     this
@@ -283,207 +283,8 @@
 %5B%5D%0A%0A
-    var configsOk = configs.every((x) =%3E %7B%0A      return typeof x.name == 'string' %7C%7C Array.isArray(x.name)%0A    %7D)%0A    if (!configsOk)%0A      throw new VError('DB configurations must provide a name')%0A%0A
     
@@ -894,22 +894,16 @@
 %7D%0A    %7D%0A
-    //
 %0A    // 
@@ -2749,24 +2749,101 @@
 err, db)=%3E%7B%0A
+        let logName = config.name %7C%7C db.databaseName // name to show in logs%0A
         if (
@@ -2900,32 +2900,28 @@
 r, %60Mongo/$%7B
-config.n
+logN
 ame%7D connect
@@ -2946,113 +2946,788 @@
     
-this%5Bconfig.name%5D = db // add connection object to the class%0A        this._mongoDbNames.push(config.name)
+let names = null%0A        if (!config.name) // use name in connection string if not defined%0A          names = %5Bdb.databaseName%5D%0A        else if (typeof config.name == 'string')%0A          names = %5Bconfig.name%5D%0A        else%0A          names = config.name%0A%0A        for (let name of names)%7B%0A          // reference db instance by adding it as class property.%0A          // if name is different than db name and more than 1 name set, reference it as instance of another db%0A          if (name === db.databaseName %7C%7C names.length == 1)%7B%0A            this%5Bname%5D = db%0A%0A            // add only the main db to the list, since there's no need to close other dbs on the same socket%0A            this._mongoDbNames.push(name)%0A          %7D%0A          else%0A            this%5Bname%5D = db.db(name)%0A        %7D%0A
 %0A   
@@ -3752,24 +3752,20 @@
 Mongo/$%7B
-config.n
+logN
 ame%7D con

Allow using multiple dbs with 1 connection