package main

import (
	"crypto/tls"
	"log"
	"server/kok"
	"server/sistem/fiko_mongo"
	"time"

	gosocketio "github.com/ambelovsky/gosf-socketio"
	"github.com/ambelovsky/gosf-socketio/transport"
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/fiber/v2/middleware/logger"
	"github.com/gofiber/fiber/v2/middleware/requestid"
)

func main() {
	app := fiber.New(fiber.Config{AppName: "FikoYT Sunucu"})
	// Mogodb İnit Ediliyor
	fiko_mongo.Init(app)
	/**/
	// Setup the middleware to retrieve the data sent in first GET request
	server := gosocketio.NewServer(transport.GetDefaultWebsocketTransport())

	// --- caller is default handlers

	//on connection handler, occurs once for each connected client
	server.On(gosocketio.OnConnection, func(c *gosocketio.Channel, args interface{}) {
		//client id is unique
		log.Println("New client connected, client id is ", c.Id())

		//you can join clients to rooms
		c.Join("room name")

		//of course, you can list the clients in the room, or account them
	})
	//on disconnection handler, if client hangs connection unexpectedly, it will still occurs
	//you can omit function args if you do not need them
	//you can return string value for ack, or return nothing for emit
	server.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel) {
		//caller is not necessary, client will be removed from rooms
		//automatically on disconnect
		//but you can remove client from room whenever you need to
		c.Leave("room name")

		log.Println("Disconnected")
	})
	//error catching handler
	server.On(gosocketio.OnError, func(c *gosocketio.Channel) {
		log.Println("Error occurs")
	})

	// --- caller is custom handler

	//custom event handler
	server.On("handle something", func(c *gosocketio.Channel, channel Channel) string {
		log.Println("Something successfully handled")

		//you can return result of handler, in caller case
		//handler will be converted from "emit" to "ack"
		return "result"
	})

	//you can get client connection by it's id
	channel, _ := server.GetChannel("client id here")
	//and send the event to the client
	type MyEventData struct {
		Data string
	}
	channel.Emit("my event", MyEventData{"my data"})

	//or you can send ack to client and get result back
	result, err := channel.Ack("my custom ack", MyEventData{"ack data"}, time.Second*5)

	//you can broadcast to all clients
	server.BroadcastToAll("my event", MyEventData{"broadcast"})

	//or for clients joined to room
	server.BroadcastTo("my room", "my event", MyEventData{"room broadcast"})

	/**/
	app.Use(logger.New())
	app.Use(requestid.New())
	//
	kok.KokRouting(app)

	// app.Get("/", func(c *fiber.Ctx) error {
	// 	return c.SendString("Hello, World!")
	// })

	// app.Get("/metrics", monitor.New(monitor.Config{Title: "FikoYT Metrikler"}))

	// app.Listen(":3000")

	runSsl(app)
}

func runSsl(app *fiber.App) {
	// Create tls certificate
	cer, err := tls.LoadX509KeyPair("cert/server.crt", "cert/server.key")
	if err != nil {
		log.Fatal(err)
	}
	config := &tls.Config{Certificates: []tls.Certificate{cer}}
	// Create custom listener
	ln, err := tls.Listen("tcp", ":3000", config)
	if err != nil {
		panic(err)
	}

	// Start server with https/ssl enabled on http://localhost:443
	log.Fatal(app.Listener(ln))
}
