import { IEvents, EventName, Key, IEntity, IVehicle, VehicleSeat } from "../../game";
import game from "../../index";
import { RageEntity, RageVehicle, RagePlayer } from "./entities";

export default class RageEvents implements IEvents {
    boundKeys: Key[] = [];

    translateEventName(event: EventName): string {
        switch (event) {
            case EventName.PlayerCommand: return "playerCommand";
            case EventName.Tick: return "render";
            case EventName.EntityStreamIn: return "entityStreamIn";
        }
    }

    add(event: EventName | string, callback: (...args: any[]) => void): void {
        var eventName: string;

        if (typeof (event) === 'string') {
            eventName = event.toString();
        } else {
            eventName = game.events.translateEventName(event);
        }

        mp.events.add(eventName, callback);
    }

    addCef(event: string, callback: (args: any[]) => void): void {
        mp.events.add('CEF:' + event, (cefArgs: string) => {
            callback(JSON.parse(cefArgs));
        });
    }

    callServer(event: string, args?: any[] | any): void {
        if (args !== null) {
            if (typeof args === 'object') {
                args.push(event);
            } else {
                args = [args, event];
            }
        } else {
            args = [event];
        }

        var params = JSON.stringify(args);

        mp.events.callRemote('CLIENT:Event', params);
    }

    bindKey(key: Key, hold: boolean, callback: Function) {
        if (this.boundKeys.indexOf(key) === -1) {
            mp.keys.bind(key, hold, callback);
            this.boundKeys.push(key);
        }
    }

    unbindKey(key: Key, hold: boolean, callback?: Function) {
        var index: number = this.boundKeys.indexOf(key);
        if (index !== -1) {
            mp.keys.unbind(key, hold, callback);
            this.boundKeys.splice(index, 1);
        }
    }


    onEntityStreamIn(callback: (entity: IEntity) => void): void {
        mp.events.add("entityStreamIn", (e: EntityMp) => {
            var rE: RageEntity;
            switch (e.type) {
                case 'vehicle':
                    rE = new RageVehicle(<VehicleMp>e);
                    break;
                case 'player':
                    rE = new RagePlayer(<PlayerMp>e);
                    break;
            }

            callback(rE);
        })
    }

    onPlayerEnterVehicle(callback: (vehicle: IVehicle, seat: VehicleSeat) => void): void {
        mp.events.add("playerEnterVehicle", (rV: VehicleMp, rS: number) => {
            callback(new RageVehicle(rV), <VehicleSeat>(rS + 1));
        });
    }

    onPlayerExitVehicle(callback: () => void): void {
        mp.events.add("playerLeaveVehicle", (rV: VehicleMp) => {
            callback();
        });
    }


    onPlayerCommand(callback: (cmd: string) => void) {
        mp.events.add("playerCommand", (cmd: string) => {
            callback(cmd);
        });
    }
}
