package messaging

import (
	"encoding/json"
	"fmt"
	gorilla_websocket "github.com/gorilla/websocket"
	"github.com/kataras/iris/v12/core/router"
	"github.com/kataras/iris/v12/websocket"
	"github.com/kataras/neffos"
	"github.com/kataras/neffos/gorilla"
	"net/http"
	"sync"
)

var locker sync.RWMutex

var namespaces = make(neffos.Namespaces, 10)

func wrapError(errorText string) []byte {
	if errorText == "" {
		jsonText, _ := json.Marshal(map[string]string{})
		return jsonText
	} else {
		jsonText, _ := json.Marshal(map[string]string{"err": errorText})
		return jsonText
	}
}

func BindRoutes(party router.Party) {
	party.Get("/ws", websocket.Handler(neffos.New(gorilla.Upgrader(gorilla_websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}), namespaces)))
}

func Register(namespaceName string, eventMapping neffos.Events) *Contexts {

	contexts := newContexts()
	eventMapping["_OnNamespaceConnected"] = func(connection *neffos.NSConn, message neffos.Message) error {
		fmt.Println("_OnNamespaceConnected")
		return nil
	}
	eventMapping["_OnNamespaceDisconnect"] = func(connection *neffos.NSConn, message neffos.Message) error {
		fmt.Println("_OnNamespaceConnected")
		contexts.remove(connection.Conn.ID())
		return nil
	}
	eventMapping["login"] = func(connection *neffos.NSConn, message neffos.Message) error {
		var headers map[string]string
		if err := json.Unmarshal(message.Body, &headers); err != nil {
			connection.Emit("onLogin", wrapError(err.Error()))
			return nil
		}
		token, ok := headers["token"]
		if !ok {
			connection.Emit("onLogin", wrapError("未找到token!"))
			return nil
		}
		delete(headers, "token")
		fmt.Println(token)
		contextID := connection.Conn.ID() // Todo 需要根据 token 解析出 user id
		if contexts.authenticator != nil {
			newContextID, err := contexts.authenticator(headers)
			if err != nil {
				connection.Emit("onLogin", wrapError(err.Error()))
				return nil
			}
			if newContextID != "" {
				contextID = newContextID
			}
		}
		contexts.add(contextID, connection)
		connection.Emit("onLogin", wrapError(""))
		return nil
	}
	namespaces[namespaceName] = eventMapping
	return contexts
}
