'use strict'

import TypeDetect from 'agilite-utils/dist/type-detect'
import EnumsTypeDetect from 'agilite-utils/dist/enums-type-detect'

// NATIVE FUNCTIONS
const find = async (
  Schema,
  qry,
  fieldsToReturn: any = undefined,
  qryOptions: any = undefined,
  page: any = undefined,
  pageLimit: any = undefined
) => {
  if (page === null || pageLimit === null) {
    return await Schema.find(qry, fieldsToReturn, qryOptions).exec()
  } else {
    return await Schema.find(qry, fieldsToReturn, qryOptions)
      .skip(page * pageLimit)
      .limit(pageLimit)
      .exec()
  }
}

const distinct = async (Schema, fieldName, conditions: any = undefined) => {
  return await Schema.distinct(fieldName, conditions)
}

const findOne = async (Schema, qry, fieldsToReturn: any = undefined, qryOptions: any = undefined) => {
  return await Schema.findOne(qry, fieldsToReturn, qryOptions).exec()
}

const create = async (Schema, entry, options: any = undefined) => {
  const doc = new Schema(entry)
  let result: any = null

  if (TypeDetect(options) !== EnumsTypeDetect.OBJECT) options = null
  result = await Schema.create([doc], options)

  return result[0]
}

const findById = async (Schema, id, fieldsToReturn: any = undefined, qryOptions: any = undefined) => {
  return await Schema.findById(id, fieldsToReturn, qryOptions).exec()
}

const findByIdAndUpdate = async (Schema, id, entry, qryOptions: any = undefined) => {
  return await Schema.findByIdAndUpdate(id, entry, qryOptions)
}

const findByIdAndDelete = async (Schema, id, qryOptions: any = undefined) => {
  return await Schema.findByIdAndDelete(id, qryOptions)
}

const findOneAndUpdate = async (Schema, qry, entry, qryOptions: any = undefined) => {
  return await Schema.findOneAndUpdate(qry, entry, qryOptions)
}

const findOneAndDelete = async (Schema, qry, qryOptions: any = undefined) => {
  return await Schema.findOneAndDelete(qry, qryOptions)
}

const deleteOne = async (Schema, qry) => {
  return await Schema.deleteOne(qry)
}

const deleteMany = async (Schema, conditions, options: any = undefined) => {
  return await Schema.deleteMany(conditions, options)
}

const updateMany = async (Schema, qry, entry, qryOptions: any = undefined) => {
  return await Schema.updateMany(qry, entry, qryOptions)
}

const insertMany = async (Schema, data) => {
  return await Schema.insertMany(data)
}

const bulkWrite = async (Schema, data, qryOptions: any = undefined) => {
  return await Schema.bulkWrite(data, qryOptions)
}

const aggregate = async (Schema, conditions) => {
  return await Schema.aggregate(conditions)
}

const countDocuments = async (Schema, conditions) => {
  return await Schema.countDocuments(conditions)
}

const estimatedDocumentCount = async (Schema, options: any = undefined) => {
  return await Schema.estimatedDocumentCount(options)
}

// EXPORTS
export default {
  find,
  distinct,
  findOne,
  create,
  findById,
  findByIdAndUpdate,
  findByIdAndDelete,
  findOneAndUpdate,
  findOneAndDelete,
  deleteOne,
  deleteMany,
  updateMany,
  insertMany,
  bulkWrite,
  aggregate,
  countDocuments,
  estimatedDocumentCount
}
