const Discord = require("discord.js");
const dbddb = require('dbdjs.db')
const {VariableManager} = require('./Variables.js')
const Blacklist = require('./Blacklist.js')
const Group = require('../CacheHandler/index.js').cache
const InteractionManager = require("./Interaction.js")
const AoiError = require('./AoiError.js')
const {ActivityTypeAvailables,IntentOptions,SlashOptionTypes} = require('../Utils/Constants.js')
const { DbdjsApi,DbdTsDb,CustomDB, Promisify}= require('./Database.js')
const CacheManager = require('./CacheManager.js')

class BaseClient extends Discord.Client {
 constructor(options){
     if(options.cache){
         options.makeCache = CacheManager._setDjsCacheManagers(options.cache)
     }
     
 if(options.presence?.activites?.length){
     if(Object.keys(ActivityTypeAvailables).includes(options.presence?.activities[0].type)  ||   Object.values( ActivityTypeAvailables ).includes( options.presence?.activities[0].type ) ){
         options.presence.activities[0].type = ActivityTypeAvailables[ options.presence?.activities[0].type ]  ||  options.presence?.activities[0].type 
         
     }
     else{
   throw new TypeError(`ActivityTypeAvailablesError:  Invalid Activity Type (${options.presence?.activities[0].type}) Provided`)
     }
 }
     
 options.partials = options.partials || ["CHANNEL", "GUILD_MEMBER", "MESSAGE", "USER", "REACTION"]
     
   options.intents =  !Array.isArray(options.intents) ?(options.intents?.toLowerCase() === "all"?IntentOptions.all : undefined):options.intents.map(x=>IntentOptions[x] || x)
     
      super (options);
     
     this.interactionManager = new InteractionManager(this)
     
     this.blacklist = new Blacklist(this)
     
     this.cacheManager = new CacheManager(this)
     
    this.variableManager = new VariableManager(this) 
     
     if( ["default","dbdjs.db","dbdjs.db-sql","dbdjs.mongo"].includes(options?.database?.type) ){
this.db = new DbdjsApi(options?.database?.db||dbddb,{
path:options?.database?.path||"./database/",
tables: options?.database?.tables||["main"]
},{type:options?.database?.type||"default",promisify:options?.database?.promisify||false},options.database?.extraOptions||{})

     }
     
 else if(options?.database?.type === "dbdts.db"){
     this.db = new DbdTsDb(options.database?.db,{path:options.database?.path||"./database",tables:options?.database?.tables||["main"]},{type:"dbdts.db", promisify:false},options.database?.extraOptions||{})
 }
     
     else if(options?.database?.type === "custom" && !options?.database?.promisify ){
this.db = new CustomDB(options?.database?.db,{path:options.database?.path||"./database",tables:options?.database?.tables||["main"]},{type:"custom", promisify:true},options.database?.extraOptions||{})
         }
    else if(options?.database?.type === "custom" && options?.database?.promisify ){
        this.db = new Promisify(options.database?.db,{path:options.database?.path||"./database",tables:options?.database?.tables||["main"]},{type:"custom", promisify:true},options.database?.extraOptions||{})
    }



if(options?.events?.functionError){
    this.on("functionError",async (data,client)=>{await require('../Handler/custom/functionError.js')(data,client)})
}
if(options?.events?.timeout){
    
}
      this.prefix = options.prefix
     Object.defineProperty(this,"statuses",{value: new Group()})
      if(options.mobilePlatform === true){
this.options.ws.properties.$browser = "Discord Android"
      }
     this.on("ready",async ()=>{require('../Handler/status.js')(this.statuses,this);
  if(options?.fetchInvites?.enabled){
      require('../Handler/fetchInvites.js')(this)
  }
     await require('../Handler/nonIntents/ready.js')(this)
        })
     this._api = (url) =>`https://discord.com/api/v9/${url.startsWith("/") ? url.slice(1) : url}`
      this.login(options.token)

       }
 status(...statuses){

 for(const status of statuses){
  status.type = (Object.keys(ActivityTypeAvailables).includes(status.type) || Object.values(ActivityTypeAvailables).includes(status.type)) ? (ActivityTypeAvailables[status.type]||status.type ): "PLAYING"
 const option = {name:status.text,type:status.type}
 if(status.url){option.url=status.url}
 this.statuses.set(this.statuses.size,{
status:status.status||"online",
time:isNaN(status.time || 12)?12:status.time,
activity:option,
afk:status.afk||false,
shardID:status.shardIDs||0
})
 }
    }
 variables(d,table=this.db.tables[0]){
  for(const [name, value] of Object.entries(d)){
      this.variableManager.add({name,value}) 
  } 
     if(this.db instanceof DbdTsDb){
         const data = this.variableManager.cache.allValues().map(x=>x.object())
         console.log(data)
         this.db.addColumns(table,data)
     }
 }
async _createCacheFactory(options){
    options.makeCache =await CacheManager._setDjsCacheManagers(options.cache) 
}

}
module.exports = BaseClient;