package main

import (
	"flag"
	"log"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"
)

func ParseFlags() (string, error) {
	// String that contains the configured configuration path
	var configPath string

	exe, _ := os.Executable()
	defaultCfgPath := filepath.Dir(exe)
	defaultCfgPath = filepath.Join(defaultCfgPath, "/config.yml")
	// Set up a CLI flag called "-config" to allow users
	// to supply the configuration file
	flag.StringVar(&configPath, "config", defaultCfgPath, "path to config file")

	// Actually parse the flags
	flag.Parse()

	// Validate the path first
	if err := ValidateConfigPath(configPath); err != nil {
		return "", err
	}

	// Return the configuration path
	return configPath, nil
}

// func getIcon(s string) []byte {
// 	b, err := ioutil.ReadFile(s)
// 	if err != nil {
// 		fmt.Print(err)
// 	}
// 	return b
// }

func main() {

	// Generate our config based on the config supplied
	// by the user in the flags
	cfgPath, err := ParseFlags()
	if err != nil {
		log.Fatal(err)
	}

	cfg := NewConfig(cfgPath)

	log := NewLog()
	log.Info("config loaded.")
	log.Infof("Callsign: %s", cfg.SQLite.Callsign)

	DeleteDatabase("./flex.sqlite", log)

	// Load country.xml to get all the DXCC
	Countries := LoadCountryFile()

	fRepo := NewFlexDXDatabase("flex.sqlite")
	defer fRepo.db.Close()

	cRepo := NewLog4OMContactsRepository(cfg.SQLite.SQLitePath)
	defer cRepo.db.Close()

	TCPServer := NewTCPServer(cfg.TelnetServer.Host, cfg.TelnetServer.Port, log)

	FlexClient := NewFlexClient(*fRepo, TCPServer)
	TCPClient := NewTCPClient(TCPServer, FlexClient, log, Countries)
	HTTPServer := NewHTTPServer(*cRepo, *fRepo, FlexClient, TCPServer, log)

	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)

	go FlexClient.StartFlexClient()
	go TCPClient.StartClient()
	go TCPServer.StartServer()

	if Cfg.General.HTTPServer {
		go HTTPServer.StartHTTPServer()
	}

	for sig := range sigCh {
		log.Infof("received signal: %v, shutting down TCP Client.", sig)

		TCPClient.Close()

		if err := fRepo.db.Close(); err != nil {
			log.Error("failed to close the database connection properly")
			os.Exit(1)
		}

		if err := cRepo.db.Close(); err != nil {
			log.Error("failed to close Log4OM database connection properly")
			os.Exit(1)
		}

		os.Exit(0)
	}

}