package cyberdaemon

// Daemonizer provides methods for daemonizing your application code.
//
// Gotchas
//
// There are several "gotchas" that implementers should be aware of when using
// the Daemonizer.
//
// System V (init.d) on Linux:
// A file known as a "PID file" is used to store the process ID of the running
// daemon's process. Both the init.d script, and daemon must know where this
// file is stored - the script to read it, and the daemon to update it. By
// default, the System V Daemonizer will attempt to find the PID file by
// looking in the init.d script for a Bash variable named:
// 	'PID_FILE_PATH'
// If it cannot locate such a variable, it will use:
// 	"/var/run/<init.d-script-name>.pid"
//
// Windows:
// On Windows, developers must implement a method named 'WindowsDaemonID'
// in their Application implementations. The Windows build of this interface
// differs from the unix variant by this one method. This is needed because
// the Windows service manager needs to know the service name when starting
// the daemon. This was implemented in the Application interface to make it
// a compile-time error if developers try to build for Windows in addition
// to other operating systems.
//
// Implementation details
//
// System V (init.d):
// System V is one of the more complicated daemon implementations in this
// library. This is due to Go's inability to fork, and the tight-knit nature of
// the daemon management script and its corresponding daemon application.
//
// System V works by using a script (typically written in Bourne Shell) to
// manage the daemon. This script is usually stored in '/etc/init.d'. System V
// expects the init.d script to exit after starting the daemon process. This is
// typically implemented using the 'fork' system call, which spawns a new
// process with only one thread. Go's runtime requires multiple threads to run
// (many Go programs rely on more than one thread anyways). An alternate
// solution is to do what is called "fork exec". This means the Go program runs
// a new instance of itself, and the original instance exits. Implementing this
// is tricky because the library cannot rely on settings files, command line
// arguments, or environment variables to determine if init.d started it. Doing
// so would cross an implementation line that would require implementers to
// bake the special business logic into their own independent init.d scripts.
//
// This library's System V daemon implementation checks the parent PID's
// "/proc/<pid>/cmdline" to determine:
// 	- Is init.d the parent process?
// 	- If so, where is the init.d script stored?
//
// If started by init.d, the daemon will attempt to parse the PID file path
// from the init.d script. A PID file is used to store the PID of the daemon
// so that the management script can easily determine the status of the daemon.
// Both the init.d script and the daemon need to know where this file is
// located (the script so that it can read it, and the daemon so that it can
// write its PID to it). If the daemon cannot find the PID file path in the
// init.d script, it uses a sane default PID file path.
type Daemonizer interface {
	// RunUntilExit runs the provided Application until the daemon is
	// instructed to quit. This method blocks until the daemon exits.
	RunUntilExit(Application) error
}

// LogConfig configures the logging settings for the daemon.
type LogConfig struct {
	// UseNativeLogger specifies whether the operating system's native
	// logging tool should be used. When set to 'true', implementers
	// should use the standard library's 'log' package to facilitate
	// logging. This guarantees that your log messages will reach the
	// native logging utility.
	//
	// For Linux systems, the native logger depends on whether systemd
	// or System V is used. Systemd saves stderr output from the daemon.
	// These logs are accessed by running:
	// 	journalctl -u myapp
	// You can add '-f' to the above command to display log messages
	// as they are created.
	// System V (init.d), however, does not provide a similar logging
	// tool. If the daemon was installed using a Controller, the stderr
	// output of the daemon will be redirected to a log file. This log
	// file can be found at:
	// 	/var/log/myapp/myapp.log
	// If a System V daemon was not installed using a controller, it will
	// attempt to output logs to stderr.
	//
	// macOS, like System V, does not provide a logging tool. If the daemon
	// was installed using a Controller, its stderr will be redirected to:
	// 	/Library/Logs/com.github.myapp/com.github.myapp.log
	// ... and user daemons will be saved to:
	// 	~/Library/Logs/com.github.myapp/com.github.myapp.log
	// If a macOS daemon was not installed using a controller, it will
	// attempt to output logs to stderr.
	//
	// Windows provides the Event Log utility for saving log messages.
	// Log messages can be viewed using either the 'Event Viewer' GUI
	// application, or by running:
	// 	TODO: Event viewer CLI command
	UseNativeLogger bool

	// NativeLogFlags specifies which log flags to use when UserNativeLogger
	// is set to 'true'. The value must be greater than zero to take effect.
	// See the standard library's 'log' package for more information about
	// log flags.
	NativeLogFlags int
}