package applog

import (
	"log"
	"os"
	"time"
)

var Enabled bool

type logToFile struct {
	fn      string
	file    *os.File
	closing chan chan error // channel to close the file. Pass a 'chan error' which returns the error
}

var ltf *logToFile

func newlogToFile(fn string) *logToFile {
	return &logToFile{
		fn:      fn,
		file:    nil,
		closing: make(chan chan error),
	}
}

func Printf(format string, a ...interface{}) {
	if Enabled {
		log.Printf(format, a...)
	}
}

func Println(a ...interface{}) {
	if Enabled {
		log.Println(a...)
	}
}

func logToFileMonitor() {
	for {
		select {
		case errc := <-ltf.closing: // a close has been requested
			if ltf.file != nil {
				log.SetOutput(os.Stderr)
				ltf.file.Close()
				ltf.file = nil
			}
			errc <- nil // pass a 'nil' error back, as everything worked fine
			return
		case <-time.After(time.Duration(5 * time.Second)):
			if fi, err := os.Stat(ltf.fn); err != nil || fi.Size() == 0 {
				// it has rotated - first check we can open the new file
				if f, err := os.OpenFile(ltf.fn, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666); err != nil {
					// Send the error to the current log file - not ideal
					log.Printf("Could not open new log file: %v", err)
				} else {
					log.SetOutput(f)
					log.Printf("Rotating log file")
					ltf.file.Close()
					ltf.file = f
				}
			}
		}
	}
}

func FileOpen(fn string) {
	ltf = newlogToFile(fn)

	var err error
	ltf.file, err = os.OpenFile(fn, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalf("Error writing log file: %v", err)
	}
	// we deliberately do not close logFile here, because we keep it open pretty much for ever

	log.SetOutput(ltf.file)
	log.Printf("Opening log file")

	go logToFileMonitor()
}

func FileClose() {
	if ltf != nil {
		log.Printf("Closing log file")
		errc := make(chan error) // pass a 'chan error' through the closing channel
		ltf.closing <- errc
		_ = <-errc         // wait until the monitor has closed the log file and exited
		close(ltf.closing) // close our 'chan error' channel
		ltf = nil
	}
}
