import * as Knex from "knex"
import { RPCExporter, Socket } from "rpclibrary";
import { RaidManagerIfc, RaidManagerFeatureIfc } from "../Components/Raid/RPCInterface";
import { UserManagerIfc, UserManagerFeatureIfc } from "../Components/User/RPCInterface";
import { CharacterManagerIfc, CharacterManagerFeatureIfc } from "../Components/Character/RPCInterface";
import { ItemManagerFeatureIfc, ItemManagerIfc } from "../Components/Item/RPCInterface";
import { GuildManagerFeatureIfc, GuildManagerIfc } from "../Components/Guild/RPCInterface";
import { ShoutboxIfc } from "../Components/Shoutbox/RPCInterface";
import { Tiers } from "./Items";
import { PubSubIfc } from "../Components/PubSub/RPCInterface";

export type FrontcraftIfc = RaidManagerIfc
                          & UserManagerIfc
                          & CharacterManagerIfc 
                          & ItemManagerIfc
                          & GuildManagerIfc
                          & ShoutboxIfc
                          & PubSubIfc

export type FrontcraftFeatureIfc = RaidManagerFeatureIfc 
                                 & UserManagerFeatureIfc
                                 & CharacterManagerFeatureIfc
                                 & ItemManagerFeatureIfc
                                 & GuildManagerFeatureIfc

export declare type NotificationSeverity = 'Info' | 'Important' | 'Error';

export type AdminConf = { 
    httpPort: number,
    dbConf:Knex.Config, 
    eventBusConf: { [topic in string]: NotificationSeverity}
}

export type TableDefiniton = {
    name: string, 
    tableBuilder: (table: Knex.CreateTableBuilder) => void
}

export type Race = "Human" | "Gnome" | "Night Elf" | "Dwarf"
export const _Race: Race[] =["Human", "Gnome", "Night Elf", "Dwarf"]
export type Rank =             "ADMIN" | "Guildmaster" | "Officer" | "Classleader" | "Raider" | "Trial" | "Social" | "Guest"
export const _Rank : Rank[] = ["ADMIN" , "Guildmaster" , "Officer" , "Classleader" , "Raider" , "Trial" , "Social" , "Guest"]
export type Class =              "Warrior" | "Rogue" | "Hunter" | "Mage" | "Warlock" | "Priest" | "Shaman" | "Paladin" | "Druid"
export const _Class : Class[] = ["Warrior" , "Rogue" , "Hunter" , "Mage" , "Warlock" , "Priest" , "Shaman" , "Paladin" , "Druid"]

export type AnyRPCExporter = RPCExporter<any,any>

export type RPCPermission = {
    rpcname: string
} & {
    [rank in Rank] : boolean
}

export type RaidData = Raid & {
    participants: {
        [clazz in Class] : (Signup & Character & Spec)[] 
    } & {
        late: (Signup & Character & Spec)[]
        bench: (Signup & Character & Spec)[] 
    }
    tokens: {
        [itemname in string]: (Character & SRToken & Item)[]
    }
    tanks: (Signup & Character & Spec)[] 
    healers: (Signup & Character & Spec)[] 
}

export type SRToken = {
    signupid?:number
    characterid: number,
    itemname: string,
    level: number
}

export type SRPriority = {
    id?:number
    race?:Race
    specid?:number,
    itemname?:string,
    description?:string,
    modifier:number
}

export type Item = {
    itemname:string
    iconname:string
    url:string
    quality:string
    hidden:boolean
    tier: Tiers
}

export type User = {
    id?: number
    username: string
    pwhash: string
    rank: Rank
    currency?: number
} & {
    [currency in Tiers]? : number
}

export type Raid = {
    id?: number
    title: string
    description: string
    start: string
    signupcount?: number
    size: number
    tier: Tiers
}

export type Signup = {
    id?:number
    raidid: number
    characterid: number
    benched: boolean
    late: boolean
}

export type Character = {
    id? : number
    charactername : string
    race: Race
    specid : number
    userid : number
}

export type Token = {
    value: string
    user_id: number
    created: number
}

export type Auth = {port: number, user: User, token: Token}

export type UserRecord = {
    user: User
    connections: {[port in number]: Socket}
    auth: Auth
}

export type Spec = {
    id?: number,
    class: Class,
    specname: string
}

export type SomeOf<T> = {
    [K in keyof T]? : T[K]
}