package main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"
	"time"
	_ "time/tzdata"

	"git.fjla.uk/owlboard/timetable-mgr/background"
	"git.fjla.uk/owlboard/timetable-mgr/dbAccess"
	"git.fjla.uk/owlboard/timetable-mgr/helpers"
	"git.fjla.uk/owlboard/timetable-mgr/log"
	"git.fjla.uk/owlboard/timetable-mgr/messaging"
	"git.fjla.uk/owlboard/timetable-mgr/vstp"
)

func main() {

	cfg, err := helpers.LoadConfig()
	if err != nil {
		fmt.Println("Error loading configuration", err)
		return
	}
	cfg.PrintConfig()

	log.Msg.Info("Initialised OwlBoard timetable-mgr " + helpers.Version)

	dbAccess.InitDataAccess(cfg)
	dbAccess.PushVersionToDb()

	// Initialise a `stop` channel to signal goroutines to cleanup
	stop := make(chan struct{})

	// Handle signals from the OS
	go handleSignals(cfg, stop)

	// Start CIF Task Ticker
	background.InitTicker(cfg, stop)

	// Test Corpus Fetching
	//corpus.RunCorpusUpdate(cfg)

	if cfg.VstpOn {
		messaging.StompInit(cfg)
		vstp.Subscribe()
	}

	<-stop
}

// Traps SIGINT and SIGTERM signals and ensures cleanup() is run
func handleSignals(cfg *helpers.Configuration, stop chan<- struct{}) {
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	sig := <-sigChan
	log.Msg.Warn("Signal received: " + sig.String())
	cleanup(cfg, stop)
}

// Cleans up open connections ready for a clean exit of the program
func cleanup(cfg *helpers.Configuration, stop chan<- struct{}) {
	log.Msg.Debug("Cleaning up open connections")
	if cfg.VstpOn {
		if messaging.Client != nil {
			log.Msg.Info("Closing STOMP Client")
			messaging.Disconnect(messaging.Client)
		}
	}
	if dbAccess.MongoClient != nil {
		log.Msg.Info("Closing MongoDB Client")
		dbAccess.CloseMongoClient()
	}
	log.Msg.Info("Signalling to other goroutines")
	close(stop)

	log.Msg.Info("Program ready to exit")
	if log.Msg != nil {
		log.Msg.Sync()
	}

	time.Sleep(500 * time.Millisecond)

	os.Exit(0)
}
