import { Inject, Module } from "../../Injector/ServiceDecorator";
import { RaidManagerIfc, RaidManagerFeatureIfc } from "./RPCInterface";
import { FrontworkComponent } from "../../Types/FrontworkComponent";
import { FrontworkAdmin } from "../../Admin/Admin";
import { TableDefiniton, Signup, Raid, User } from "../../Types/Types";
import { IAdmin } from "../../Admin/Interface";

@Module()
export class RaidManager
implements FrontworkComponent<RaidManagerIfc, RaidManagerFeatureIfc>{
    name = "RaidManager" as "RaidManager";    

    @Inject(IAdmin)
    private admin: FrontworkAdmin

    exportRPCs = () => [{
        name: 'getRaids' as 'getRaids',
        call: this.getRaids
    },]

    exportRPCFeatures() {
        return [{
            name: 'manageRaid' as 'manageRaid',
            exportRPCs: () => [{
                name: 'createRaid' as 'createRaid',
                call: this.createRaid
            },{
                name: 'addSignup' as 'addSignup',
                call: this.addSignup
            },{
                name: 'removeSignup' as 'removeSignup',
                call: this.removeSignup
            }]
        },{
            name: 'signup' as 'signup',
            exportRPCs: () => [{
                name: 'getSingups' as 'getSingups',
                call: this.getSignups
            },{
                name: 'sign' as 'sign',
                call: this.sign
            }]
        },]
    }
    
    getTableDefinitions(): TableDefiniton[] {
        return [
            {
                name: 'raids',
                tableBuilder: (table) => {
                    table.increments('id').primary()
                    table.dateTime('start').notNullable()
                    table.string('description').notNullable()
                    table.string('title').notNullable()
                    table.integer('minrank').notNullable()
                }
            },{
                name: 'signups',
                tableBuilder: (table) => {
                    table.primary(['raid_id', 'user_id'])
                    table.integer('raid_id')
                    table.foreign('raid_id').references('id').inTable('raids')
                    table.integer('user_id')
                    table.foreign('user_id').references('id').inTable('users')
                }
            }            
        ]
    }

    createRaid = async (raid:Raid) => await this.admin
    .knex('raids')
    .insert(raid)
    
    addSignup = async (signup: Signup) => await this.admin
    .knex('signups')
    .insert(signup)
    
    removeSignup = async (signup: Signup) => await this.admin
    .knex('signups')
    .where({
        raid_id: signup.raid_id, 
        user_id: signup.user_id
    })
    .delete()

    getRaids = async () : Promise<Raid[]> => await this.admin.knex
    .select('*')
    .from('raids')
    
    getSignups = async (raid:Raid) => await this.admin.knex
    .select('*')
    .from('signups')
    .where('raid_id', '=', raid.id!)
    
    sign = async (user:User, raid:Raid) => await this.admin
    .knex('signups')
    .insert({
        raid_id: raid.id!,
        user_id: user.id!
    })
}