/* global process */
const log = require("../utils/logs.utils"); // Log Helper

const dbUser = process.env.OWL_DB_USER || "owl";
const dbPass = process.env.OWL_DB_PASS || "twittwoo";
const dbName = process.env.OWL_DB_NAME || "owlboard";
const dbPort = process.env.OWL_DB_PORT || 27017;
const dbHost = process.env.OWL_DB_HOST || "localhost";
const uri = `mongodb://${dbUser}:${dbPass}@${dbHost}:${dbPort}`;

const { MongoClient } = require("mongodb");

const client = new MongoClient(uri);
const db = client.db(dbName);

async function query(collection, query, returnId = false) {
  await client.connect();
  log.out(`dbAccess.query: Connecting to collection: '${collection}'`, "info");
  var qcoll = db.collection(collection);
  var qcursor = qcoll.find(query);
  if (!returnId) {
    qcursor.project({ _id: 0 });
  }
  log.out(`dbAccess.query: Running Query: ${JSON.stringify(query)}`, "info");
  increment(collection);
  log.out("dbAccess.query: Query response:");
  let result = await qcursor.toArray();
  console.log(result);
  return result;
}

async function queryProject(collection, query, projection) {
  await client.connect();
  log.out(`dbAccess.queryProject: Connecting to col: '${collection}'`, "info");
  const qcoll = db.collection(collection);
  const qcursor = qcoll.find(query).project(projection);
  log.out(
    `dbAccess.query: Running Query: ${JSON.stringify(
      query
    )}, Projection: ${JSON.stringify(projection)}`,
    "dbug"
  );
  increment(collection);
  return await qcursor.toArray();
}

async function queryAggregate(collection, pipeline) {
  await client.connect();
  log.out(`dbAccess.queryProject: Connecting to col: '${collection}'`, "info");
  log.out(
    `dbAccess.query: Running Aggregation: ${JSON.stringify(pipeline)}`,
    "dbug"
  );
  increment(collection);
  return await db.collection(collection).aggregate(pipeline).toArray();
}

async function increment(target) {
  log.out(`dbAccess.increment: Incrementing counter for: ${target}`, "info");
  await client.connect();
  let col = db.collection("meta");
  let update = {};
  update[target] = 1;
  col.updateOne({ target: "counters" }, { $inc: update });
}

async function addUser(uuid, domain) {
  // Needs testing
  log.out("dbAccess.addUser: Adding user to database");
  let doc = { uuid: uuid, domain: domain, atime: new Date() };
  await client.connect();
  let col = db.collection("users");
  let res = await col.insertOne(doc);
  if (res.insertedId) {
    return true;
  }
  return false;
}

async function addRegReq(uuid, domain) {
  // Needs testing
  log.out("dbAccess.addRegReq: Adding registration request");
  let doc = { uuid: uuid, time: new Date(), domain: domain };
  await client.connect();
  let col = db.collection("registrations");
  let res = col.insertOne(doc);
  return res;
}

async function userAtime(uuid) {
  // Needs testing
  log.out("dbAccess.userAtime: Updating access time for user");
  let q = { uuid: uuid };
  let n = { $set: { uuid: uuid, atime: new Date() } };
  await client.connect();
  let col = db.collection("users");
  let res = col.updateOne(q, n, { upsert: true });
  return res;
}

// Deletes one single registration request entry from the DB
async function delRegReq(uuid) {
  log.out("dbAccess.delRegReq: Deleting a Registration Request");
  let collection = "registrations";
  await client.connect();
  let col = db.collection(collection);
  col.deleteOne({ uuid: uuid });
}

async function colCount(collection) {
  log.out(`dbAccess.colCount: Counting entries in collection: ${collection}`);
  await client.connect();
  let col = db.collection(collection);
  let count = col.countDocuments();
  log.out(
    `dbAccess.colCount: Collection: ${collection} contains ${count}` +
      " documents"
  );
  return await count;
}

module.exports = {
  query,
  queryProject,
  queryAggregate,
  increment,
  addUser,
  userAtime,
  addRegReq,
  delRegReq,
  colCount,
};
