// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package capnslog

import (
	
	
	
	
	
	
	
)

type Formatter interface {
	Format(pkg string, level LogLevel, depth int, entries ...interface{})
	Flush()
}

func ( io.Writer) Formatter {
	return &StringFormatter{
		w: bufio.NewWriter(),
	}
}

type StringFormatter struct {
	w *bufio.Writer
}

func ( *StringFormatter) ( string,  LogLevel,  int,  ...interface{}) {
	 := time.Now().UTC()
	.w.WriteString(.Format(time.RFC3339))
	.w.WriteByte(' ')
	writeEntries(.w, , , , ...)
	.Flush()
}

func writeEntries( *bufio.Writer,  string,  LogLevel,  int,  ...interface{}) {
	if  != "" {
		.WriteString( + ": ")
	}
	 := fmt.Sprint(...)
	 := strings.HasSuffix(, "\n")
	.WriteString()
	if ! {
		.WriteString("\n")
	}
}

func ( *StringFormatter) () {
	.w.Flush()
}

func ( io.Writer,  bool) Formatter {
	return &PrettyFormatter{
		w:     bufio.NewWriter(),
		debug: ,
	}
}

type PrettyFormatter struct {
	w     *bufio.Writer
	debug bool
}

func ( *PrettyFormatter) ( string,  LogLevel,  int,  ...interface{}) {
	 := time.Now()
	 := .Format("2006-01-02 15:04:05")
	.w.WriteString()
	 := .Nanosecond() / 1000
	.w.WriteString(fmt.Sprintf(".%06d", ))
	if .debug {
		, , ,  := runtime.Caller() // It's always the same number of frames to the user's call.
		if ! {
			 = "???"
			 = 1
		} else {
			 := strings.LastIndex(, "/")
			if  >= 0 {
				 = [+1:]
			}
		}
		if  < 0 {
			 = 0 // not a real line number
		}
		.w.WriteString(fmt.Sprintf(" [%s:%d]", , ))
	}
	.w.WriteString(fmt.Sprint(" ", .Char(), " | "))
	writeEntries(.w, , , , ...)
	.Flush()
}

func ( *PrettyFormatter) () {
	.w.Flush()
}

// LogFormatter emulates the form of the traditional built-in logger.
type LogFormatter struct {
	logger *log.Logger
	prefix string
}

// NewLogFormatter is a helper to produce a new LogFormatter struct. It uses the
// golang log package to actually do the logging work so that logs look similar.
func ( io.Writer,  string,  int) Formatter {
	return &LogFormatter{
		logger: log.New(, "", ), // don't use prefix here
		prefix: ,               // save it instead
	}
}

// Format builds a log message for the LogFormatter. The LogLevel is ignored.
func ( *LogFormatter) ( string,  LogLevel,  int,  ...interface{}) {
	 := fmt.Sprint(...)
	 := .prefix
	if  != "" {
		 = fmt.Sprintf("%s%s: ", , )
	}
	.logger.Output(5, fmt.Sprintf("%s%v", , )) // call depth is 5
}

// Flush is included so that the interface is complete, but is a no-op.
func ( *LogFormatter) () {
	// noop
}

// NilFormatter is a no-op log formatter that does nothing.
type NilFormatter struct {
}

// NewNilFormatter is a helper to produce a new LogFormatter struct. It logs no
// messages so that you can cause part of your logging to be silent.
func () Formatter {
	return &NilFormatter{}
}

// Format does nothing.
func ( *NilFormatter) ( string,  LogLevel,  int,  ...interface{}) {
	// noop
}

// Flush is included so that the interface is complete, but is a no-op.
func ( *NilFormatter) () {
	// noop
}