package net.cobem.grizzly.communication;

import net.cobem.grizzly.Grizzly;
import net.cobem.grizzly.communication.events.catalog.GetPromotedRoomsDataEvent;
import net.cobem.grizzly.communication.events.catalog.InitializeCatalogEvent;
import net.cobem.grizzly.communication.events.catalog.InitializeCatalogPageEvent;
import net.cobem.grizzly.communication.events.catalog.PurchaseCatalogItemEvent;
import net.cobem.grizzly.communication.events.guild.CreateGuildEvent;
import net.cobem.grizzly.communication.events.guild.FinishCreateGuildEvent;
import net.cobem.grizzly.communication.events.handshake.*;
import net.cobem.grizzly.communication.events.messenger.AcceptFriendRequestEvent;
import net.cobem.grizzly.communication.events.messenger.FollowFriendEvent;
import net.cobem.grizzly.communication.events.messenger.RequestFriendshipEvent;
import net.cobem.grizzly.communication.events.messenger.SendInstantMessageEvent;
import net.cobem.grizzly.communication.events.misc.SaveNewNameEvent;
import net.cobem.grizzly.communication.events.misc.SendHotelViewPieceEvent;
import net.cobem.grizzly.communication.events.misc.ValidateNewNameEvent;
import net.cobem.grizzly.communication.events.navigator.*;
import net.cobem.grizzly.communication.events.rooms.*;
import net.cobem.grizzly.communication.events.stream.FriendStreamLikeStatusEvent;
import net.cobem.grizzly.communication.events.stream.FriendStreamSetStatusEvent;
import net.cobem.grizzly.communication.events.stream.InitializeFriendStreamEvent;
import net.cobem.grizzly.communication.events.tests.CheckQuizEvent;
import net.cobem.grizzly.communication.events.tests.InitializeQuizEvent;
import net.cobem.grizzly.communication.events.trading.*;
import net.cobem.grizzly.communication.events.user.*;
import net.cobem.grizzly.communication.events.wired.SaveWiredEffectEvent;
import net.cobem.grizzly.communication.events.wired.SaveWiredTriggerEvent;
import net.cobem.grizzly.habbohotel.sessions.Session;

import java.util.HashMap;
import java.util.Map;

public class EventHandler {
    private Map<Short, GameEvent> MessageLibrary;

    public EventHandler() {
        MessageLibrary = new HashMap<>();

        RegisterHandshake();
        RegisterUser();
        RegisterMessenger();
        RegisterCatalog();
        RegisterNavigator();
        RegisterRoom();
        RegisterItems();
        RegisterStream();
        RegisterModeration();
        RegisterMisc();
        RegisterGuild();
        RegisterWired();
    }

    private void RegisterHandshake() {
        MessageLibrary.put((short) 4000, new ReadReleaseEvent());
        MessageLibrary.put(HeaderLibrary.SendSecretKeyComposer, new SendTokenEvent());
        MessageLibrary.put(HeaderLibrary.InitializeCryptoComposer, new InitializeCryptoEvent());
        MessageLibrary.put(HeaderLibrary.GetMachineIDComposer, new UniqueIdEvent());
        MessageLibrary.put(HeaderLibrary.GetUserTicketComposer, new SSOTicketEvent());
    }

    private void RegisterUser() {
        MessageLibrary.put(HeaderLibrary.LoadProfileInformationComposer, new LoadUserProfileEvent());
        MessageLibrary.put(HeaderLibrary.LoadUserInformationComposer, new LoadUserDataEvent());
        MessageLibrary.put(HeaderLibrary.SetHomeRoomComposer, new SetHomeRoomEvent());
        MessageLibrary.put(HeaderLibrary.ModifyMottoComposer, new ChangeMottoEvent());
        MessageLibrary.put(HeaderLibrary.WearBadgeComposer, new WearBadgeEvent());
        MessageLibrary.put(HeaderLibrary.LoadUserTagsComposer, new LoadUserTagsEvent());
    }

    private void RegisterMessenger() {
        MessageLibrary.put(HeaderLibrary.AcceptFriendRequestComposer, new AcceptFriendRequestEvent());
        MessageLibrary.put(HeaderLibrary.SendInstantMessageComposer, new SendInstantMessageEvent());
        MessageLibrary.put(HeaderLibrary.SendFriendRequestComposer, new RequestFriendshipEvent());
        MessageLibrary.put(HeaderLibrary.FollowFriendComposer, new FollowFriendEvent());
    }

    private void RegisterCatalog() {
        MessageLibrary.put(HeaderLibrary.LoadCatalogIndexComposer, new InitializeCatalogEvent());
        MessageLibrary.put(HeaderLibrary.LoadCatalogPageComposer, new InitializeCatalogPageEvent());
        MessageLibrary.put(HeaderLibrary.PurchaseFromCatalogComposer, new PurchaseCatalogItemEvent());
        MessageLibrary.put(HeaderLibrary.GetPromotedRoomsCreationDataComposer, new GetPromotedRoomsDataEvent());
    }

    private void RegisterNavigator() {
        MessageLibrary.put(HeaderLibrary.RoomCreationCheckComposer, new RoomCreationCheckEvent());
        MessageLibrary.put(HeaderLibrary.RoomCreationComposer, new CreateRoomEvent());
        MessageLibrary.put(HeaderLibrary.LoadUserRoomsComposer, new ViewMyRoomsEvent());
        MessageLibrary.put(HeaderLibrary.LoadPopulatedRoomsComposer, new LoadPopulatedRoomsEvent());
        MessageLibrary.put(HeaderLibrary.RoomSearchComposer, new SearchRoomEvent());
    }

    private void RegisterRoom() {
        //Enter & Leave Events
        MessageLibrary.put(HeaderLibrary.LoadUserRoomComposer, new InitializeRoomEvent());
        MessageLibrary.put(HeaderLibrary.LeaveRoomComposer, new LeaveRoomEvent());

        //Loading stuff..
        MessageLibrary.put(HeaderLibrary.LoadRoomInformationComposer, new FinishRoomLoadEvent());
        MessageLibrary.put(HeaderLibrary.ParseRoomHeightMapComposer, new ParseHeightMapEvent());

        //Talking & Walking
        MessageLibrary.put(HeaderLibrary.RoomTalkComposer, new SayEvent());
        MessageLibrary.put(HeaderLibrary.RoomShoutComposer, new ShoutEvent());
        MessageLibrary.put(HeaderLibrary.RoomMovementComposer, new MovementEvent());
        MessageLibrary.put(HeaderLibrary.RoomWhisperComposer, new WhisperEvent());

        //Me Menu Actions
        MessageLibrary.put(HeaderLibrary.RoomWaveComposer, new WaveEvent());
        MessageLibrary.put(HeaderLibrary.RoomShowSignComposer, new ShowSignEvent());
        MessageLibrary.put(HeaderLibrary.RoomDanceComposer, new DanceEvent());
        MessageLibrary.put(HeaderLibrary.RoomSitComposer, new SitEvent());

        //Typing Events
        MessageLibrary.put(HeaderLibrary.InitializeTypeBubbleComposer, new StartTypingEvent());
        MessageLibrary.put(HeaderLibrary.EndTypeBubbleComposer, new EndTypingEvent());

        //Eh?
        MessageLibrary.put(HeaderLibrary.ModifyLookComposer, new ChangeLooksEvent());

        //Drop & Pickup Items
        MessageLibrary.put(HeaderLibrary.PlaceItemComposer, new PlaceItemEvent());
        MessageLibrary.put(HeaderLibrary.RemoveRoomItemComposer, new RemoveItemEvent());
        MessageLibrary.put(HeaderLibrary.RoomPlaceEffectComposer, new PlaceRoomEvent());

        //Move Items..
        MessageLibrary.put(HeaderLibrary.RepositionItemComposer, new ItemPositionChangeEvent());
        MessageLibrary.put(HeaderLibrary.RepositionWallItemComposer, new ItemPositionChangeEvent());
        MessageLibrary.put(HeaderLibrary.ToggleWallStateComposer, new ChangeWallStateEvent());
        MessageLibrary.put(HeaderLibrary.RepositionFloorItemComposer, new ChangeStateEvent());
        MessageLibrary.put(HeaderLibrary.SaveRoomBackgroundComposer, new SaveRoomBackgroundEvent());
        MessageLibrary.put(HeaderLibrary.RedeemExchangeComposer, new RedeemExchangeEvent());

        //Dice
        MessageLibrary.put(HeaderLibrary.RollDiceComposer, new RollDiceEvent());
        MessageLibrary.put(HeaderLibrary.CloseDiceComposer, new CloseDiceEvent());

        //Mod Actions
        MessageLibrary.put(HeaderLibrary.RoomRemoveUserComposer, new KickUserEvent());
        MessageLibrary.put(HeaderLibrary.GiveRespectComposer, new GiveRespectEvent());
        MessageLibrary.put(HeaderLibrary.GiveRoomRightsComposer, new GiveRightsEvent());
        MessageLibrary.put(HeaderLibrary.RoomIgnoreUserComposer, new IgnoreUserEvent());
        MessageLibrary.put(HeaderLibrary.RoomListenUserComposer, new ListenUserEvent());

        //Trading
        MessageLibrary.put(HeaderLibrary.InitializeTradeComposer, new InitializeTradeEvent());
        MessageLibrary.put(HeaderLibrary.InsertItemToTradeComposer, new AddItemToTradeEvent());
        MessageLibrary.put(HeaderLibrary.RemoveItemFromTradeComposer, new RemoveItemFromTradeEvent());
        MessageLibrary.put(HeaderLibrary.CancelTradeComposer, new CancelTradeEvent());
        MessageLibrary.put(HeaderLibrary.AcceptTradeComposer, new AcceptTradeEvent());
        MessageLibrary.put(HeaderLibrary.UndoAcceptTradeComposer, new UnacceptTradeEvent());
        MessageLibrary.put(HeaderLibrary.ConfirmTradeComposer, new ConfirmTradeEvent());

        //Badges
        MessageLibrary.put(HeaderLibrary.ViewUserBadgesComposer, new ViewUserBadgesEvent());

        //
        MessageLibrary.put((short) 1677, new CustomizeRoomEvent());
    }

    private void RegisterItems() {
        MessageLibrary.put(HeaderLibrary.InitializeFloorItemsComposer, new InitializeInventoryEvent());
    }

    private void RegisterModeration() {
        /*MessageLibrary.put(HeaderLibrary.ModToolsShowRoomInformationComposer, new ShowRoomInformationEvent());
        MessageLibrary.put(HeaderLibrary.ModToolsTravelToRoomComposer, new ModeratorEnterRoomEvent());
        MessageLibrary.put(HeaderLibrary.ModToolsAlertRoomComposer, new RoomAlertEvent());
        MessageLibrary.put(HeaderLibrary.ModToolsShowUserInformationComposer, new ShowUserInformationEvent());  */
    }

    private void RegisterMisc() {
        MessageLibrary.put(HeaderLibrary.CheckNameChangeComposer, new ValidateNewNameEvent());
        MessageLibrary.put(HeaderLibrary.CompleteNameChangeComposer, new SaveNewNameEvent());
        MessageLibrary.put(HeaderLibrary.CancelChangeNameComposer, new SaveNewNameEvent());

        MessageLibrary.put(HeaderLibrary.InitializeQuizComposer, new InitializeQuizEvent());
        MessageLibrary.put(HeaderLibrary.CheckQuizComposer, new CheckQuizEvent());

        MessageLibrary.put(HeaderLibrary.SendHotelViewPieceComposer, new SendHotelViewPieceEvent());
    }

    private void RegisterStream() {
        MessageLibrary.put(HeaderLibrary.InitializeFriendStreamComposer, new InitializeFriendStreamEvent());
        MessageLibrary.put(HeaderLibrary.FriendStreamSendMessageComposer, new FriendStreamSetStatusEvent());
        MessageLibrary.put(HeaderLibrary.FriendStreamLikeMessageComposer, new FriendStreamLikeStatusEvent());
    }

    private void RegisterGuild() {
        MessageLibrary.put(HeaderLibrary.InitializeCreateGroupComposer, new CreateGuildEvent());
        MessageLibrary.put((short) 1258, new FinishCreateGuildEvent());
    }

    private void RegisterWired() {
        MessageLibrary.put(HeaderLibrary.SaveWiredEffectComposer, new SaveWiredEffectEvent());
        MessageLibrary.put(HeaderLibrary.SaveWiredTriggerComposer, new SaveWiredTriggerEvent());
    }

    public void handleRequest(Session Session, EventRequest Message) throws Exception {

        if (!MessageLibrary.containsKey(Message.header())) {
            if (Message.body().length() >= 3) {
                //Grizzly.write("[UNKNOWN][#" + Message.header() + "] [" + Message.body() + "]");
                return;
            }
        }

        if (Grizzly.getConfig().get("net.grizzly.packetlog").equals("1")) {
            Grizzly.write("[" + Message.header() + "] " + Message.body() + " sent to " + Session.ip());
        }

        if (this.MessageLibrary.containsKey(Message.header())) {
            Grizzly.write("[#" + Message.header() + "] [" + Message.body() + "] " + this.MessageLibrary.get(Message.header()).toString());

            this.MessageLibrary.get(Message.header()).compose(Session, Message);
        }
    }
}
