package main

import (
	"flag"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"

	"git.autistici.org/ai3/go-common/unix"
	"github.com/coreos/go-systemd/v22/daemon"
	"gopkg.in/yaml.v3"

	"git.autistici.org/id/keystore/dovecot"
)

var (
	configFile              = flag.String("config", "/etc/keystore/dovecot.yml", "path of config file")
	socketPath              = flag.String("socket", "/run/dovecot-keystored/socket", "`path` to the UNIX socket to listen on")
	systemdSocketActivation = flag.Bool("systemd-socket", false, "use SystemD socket activation")
	requestTimeout          = flag.Duration("timeout", 10*time.Second, "timeout for incoming requests")
)

// Read YAML config.
func loadConfig() (*dovecot.Config, error) {
	f, err := os.Open(*configFile)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	var config dovecot.Config
	if err := yaml.NewDecoder(f).Decode(&config); err != nil {
		return nil, err
	}
	return &config, nil
}

func main() {
	log.SetFlags(0)
	flag.Parse()

	syscall.Umask(007)

	config, err := loadConfig()
	if err != nil {
		log.Fatal(err)
	}

	ddp, err := dovecot.NewKeyLookupProxy(config)
	if err != nil {
		log.Fatal(err)
	}

	srv := unix.NewLineServer(dovecot.NewDictProxyServer(ddp))
	srv.RequestTimeout = *requestTimeout

	var sockSrv *unix.SocketServer
	if *systemdSocketActivation {
		sockSrv, err = unix.NewSystemdSocketServer(srv)
	} else {
		sockSrv, err = unix.NewUNIXSocketServer(*socketPath, srv)
	}
	if err != nil {
		log.Fatalf("error: %v", err)
	}

	done := make(chan struct{})
	sigCh := make(chan os.Signal, 1)
	go func() {
		<-sigCh
		log.Printf("terminating")
		sockSrv.Close()
		close(done)
	}()
	signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)

	log.Printf("starting")
	daemon.SdNotify(false, "READY=1")
	if err := sockSrv.Serve(); err != nil {
		log.Fatal(err)
	}

	<-done
}