package main

import (
	"os"
	"playback-device-server/data"
	"playback-device-server/management"
	"playback-device-server/server"
	"sync"

	"github.com/rs/zerolog"
	"github.com/rs/zerolog/log"
)

func main() {
	initializeLogger()
	log.Info().Msg("starting playback device server")

	configuration, err := LoadConfiguration("config.json")
	if err != nil {
		log.Error().Err(err).Msg("configuration error")
		os.Exit(1)
	}

	userDatabase := data.UserDatabase{}
	userDatabase.SetDirectory(configuration.DatabaseDirectory)
	err = userDatabase.Initialize()
	if err != nil {
		log.Error().Err(err).Msg("failed to initialize user database")
		os.Exit(1)
	}
	defer userDatabase.Close()

	deviceDatabase := data.DeviceDatabase{}
	deviceDatabase.SetDirectory(configuration.DatabaseDirectory)
	err = deviceDatabase.Initialize()
	if err != nil {
		log.Error().Err(err).Msg("failed to initialize device database")
		os.Exit(1)
	}
	defer deviceDatabase.Close()

	userManager := management.UserManager{}
	err = userManager.Initialize(&userDatabase)
	if err != nil {
		log.Error().Err(err).Msg("failed to initialize user manager")
	}

	deviceManager := management.DeviceManager{}
	err = deviceManager.Initialize(&deviceDatabase)
	if err != nil {
		log.Error().Err(err).Msg("failed to initialize device manager")
	}

	webServer := server.WebServer{}
	webServer.SetWebAppDirectoryPath("www")
	webServer.SetPort(configuration.Port)
	webServer.Initialize()
	defer webServer.Close()

	authenticator := server.Authenticator{}
	authenticator.SetUserManager(&userManager)
	authenticator.SetDeviceManager(&deviceManager)

	userApiHandler := server.UsersApiHandler{}
	userApiHandler.SetUserManager(&userManager)
	userApiHandler.SetRouter(webServer.Router())
	userApiHandler.Initialize(&authenticator)

	deviceApiHandler := server.DeviceApiHandler{}
	deviceApiHandler.SetDeviceManager(&deviceManager)
	deviceApiHandler.SetRouter(webServer.Router())
	deviceApiHandler.Initialize(&authenticator)

	webSocketServer := server.WebsocketServer{}
	webSocketServer.SetRouter(webServer.Router())
	webSocketServer.Initialize(&authenticator)

	webRTCWSHandler := server.WebRTCWSHandler{}
	webSocketServer.AddHandler(&webRTCWSHandler)

	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		defer wg.Done()
		log.Info().Msg("starting web server")
		err := webServer.Start()
		if err != nil {
			log.Error().Err(err).Msg("failed to start web server")
		}
	}()
	wg.Wait()
}

func initializeLogger() {
	zerolog.TimeFieldFormat = zerolog.TimeFormatUnixMs

	file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		log.Printf("failed to open log file: %v", err)
	}

	consoleWriter := zerolog.ConsoleWriter{Out: os.Stdout}
	multi := zerolog.MultiLevelWriter(consoleWriter, file)
	log.Logger = zerolog.New(multi).With().Timestamp().Logger()
}
