package main

import (
	"encoding/json"
	"log"
	"math/rand"
	"net/http"

	wss "git.alfi.li/gamelang/frontend/wsserver"
	gamelangpb "git.alfi.li/gamelang/protobuf/gamelang"
	um "git.alfi.li/gamelang/systems/usermanager"
	wm "git.alfi.li/gamelang/systems/worldmanager"
)

type ExampleConfig struct {
	Http struct {
		Listen string // ip:port
	}
	Kafka struct {
		Enabled            bool
		UserManagerBroker  string
		WorldManagerBroker string
	}
}

func DefaultConfig() ExampleConfig {
	config := ExampleConfig{}
	config.Http.Listen = "0.0.0.0:8080"
	config.Kafka.Enabled = false
	return config
}

type exampleWSServer struct {
	wsserver     wss.WSServer
	usermanager  um.UserManager
	worldmanager wm.WorldManager
}

func (ewss exampleWSServer) RenderHandler() []wss.Handler {
	handler := []wss.Handler{}
	handler = append(handler, wss.Handler{MType: "echo", Callback: func(msg wss.WSMsg, user gamelangpb.User) (wss.WSMsg, error) {
		log.Printf("echo from \"%s\" with \"%s\"", user, msg.Payload)
		remsg := wss.WSMsg{Mtype: "echo", Payload: msg.Payload}
		return remsg, nil
	}})

	handler = append(handler, wss.Handler{MType: "world:create", Callback: func(msg wss.WSMsg, user gamelangpb.User) (wss.WSMsg, error) {
		_, err := ewss.worldmanager.Create(rand.Uint32(), msg.Payload)
		if err != nil {
			remsg := wss.WSMsg{Mtype: "world:create", Payload: "failed"}
			return remsg, err
		}
		remsg := wss.WSMsg{Mtype: "world:create", Payload: "success"}
		return remsg, nil
	}})

	handler = append(handler, wss.Handler{MType: "world:remove", Callback: func(msg wss.WSMsg, user gamelangpb.User) (wss.WSMsg, error) {
		err := ewss.worldmanager.Remove(msg.Payload)
		if err != nil {
			remsg := wss.WSMsg{Mtype: "world:remove", Payload: "failed"}
			return remsg, err
		}
		remsg := wss.WSMsg{Mtype: "world:remove", Payload: "success"}
		return remsg, nil
	}})

	handler = append(handler, wss.Handler{MType: "world:join", Callback: func(msg wss.WSMsg, user gamelangpb.User) (wss.WSMsg, error) {
		err := ewss.worldmanager.Join(msg.Payload, &user)
		if err != nil {
			remsg := wss.WSMsg{Mtype: "world:join", Payload: "failed"}
			return remsg, err
		}
		remsg := wss.WSMsg{Mtype: "world:join", Payload: "success"}
		return remsg, nil
	}})

	handler = append(handler, wss.Handler{MType: "world:list", Callback: func(msg wss.WSMsg, user gamelangpb.User) (wss.WSMsg, error) {
		log.Print("world:list")
		worldlist := ewss.worldmanager.List()
		worldlistJSON, err := json.Marshal(worldlist)
		if err != nil {
			msg := wss.WSMsg{Mtype: "world:list", Payload: "failed"}
			return msg, err
		}
		log.Print("world:list", "sending list")
		remsg := wss.WSMsg{Mtype: "world:list", Payload: string(worldlistJSON)}
		return remsg, nil
	}})
	return handler
}

func main() {
	brokers := []string{}

	usermanager := um.NewUserManager(brokers)
	log.Print("usermanager initialized")

	worldmanager := wm.NewWorldManager(brokers)
	log.Print("worldmanager initialized")

	wsserver := wss.NewWSServer([]string{})

	ewss := exampleWSServer{usermanager: *usermanager, worldmanager: *worldmanager, wsserver: *wsserver}
	ewss.wsserver.RegisterHandler(ewss.RenderHandler())

	http.HandleFunc("/ws", ewss.wsserver.WebsocketHandler)
	log.Println("websocket listening on", ":8080")
	http.ListenAndServe(":8080", nil)
}
