package middleware

import (
	"log"
	"net/http"
	"os"
)

func RequestLog(p parser) Middleware {
	var logWhat, outputFile, format string
	var logger *log.Logger

	for p.Next() {
		p.Args(&logWhat, &outputFile, &format)

		if logWhat == "" {
			return p.ArgErr()
		}
		if outputFile == "" {
			outputFile = defaultLogFilename
		}
		switch format {
		case "":
			format = defaultReqLogFormat
		case "{common}":
			format = commonLogFormat
		case "{combined}":
			format = combinedLogFormat
		}
	}

	// Open the log file for writing when the server starts
	p.Startup(func() error {
		var err error
		var file *os.File

		if outputFile == "stdout" {
			file = os.Stdout
		} else if outputFile == "stderr" {
			file = os.Stderr
		} else {
			file, err = os.OpenFile(outputFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
			if err != nil {
				return err
			}
		}

		logger = log.New(file, "", 0)
		return nil
	})

	return func(next http.HandlerFunc) http.HandlerFunc {
		return func(w http.ResponseWriter, r *http.Request) {
			sw := newResponseRecorder(w)
			next(sw, r)
			rep := newReplacer(r, sw)
			logger.Println(rep.replace(format))
		}
	}
}

const (
	defaultLogFilename  = "access.log"
	commonLogFormat     = `{remote} ` + emptyStringReplacer + ` [{when}] "{method} {uri} {proto}" {status} {size}`
	combinedLogFormat   = commonLogFormat + ` "{>Referer}" "{>User-Agent}"`
	defaultReqLogFormat = commonLogFormat
)