package log

import (
	
	
	
	
	
)

type jsonLogger struct {
	io.Writer
}

// NewJSONLogger returns a Logger that encodes keyvals to the Writer as a
// single JSON object. Each log event produces no more than one call to
// w.Write. The passed Writer must be safe for concurrent use by multiple
// goroutines if the returned Logger will be used concurrently.
func ( io.Writer) Logger {
	return &jsonLogger{}
}

func ( *jsonLogger) ( ...interface{}) error {
	 := (len() + 1) / 2 // +1 to handle case when len is odd
	 := make(map[string]interface{}, )
	for  := 0;  < len();  += 2 {
		 := []
		var  interface{} = ErrMissingValue
		if +1 < len() {
			 = [+1]
		}
		merge(, , )
	}
	 := json.NewEncoder(.Writer)
	.SetEscapeHTML(false)
	return .Encode()
}

func merge( map[string]interface{}, ,  interface{}) {
	var  string
	switch x := .(type) {
	case string:
		 = 
	case fmt.Stringer:
		 = safeString()
	default:
		 = fmt.Sprint()
	}

	// We want json.Marshaler and encoding.TextMarshaller to take priority over
	// err.Error() and v.String(). But json.Marshall (called later) does that by
	// default so we force a no-op if it's one of those 2 case.
	switch x := .(type) {
	case json.Marshaler:
	case encoding.TextMarshaler:
	case error:
		 = safeError()
	case fmt.Stringer:
		 = safeString()
	}

	[] = 
}

func safeString( fmt.Stringer) ( string) {
	defer func() {
		if  := recover();  != nil {
			if  := reflect.ValueOf(); .Kind() == reflect.Ptr && .IsNil() {
				 = "NULL"
			} else {
				 = fmt.Sprintf("PANIC in String method: %v", )
			}
		}
	}()
	 = .String()
	return
}

func safeError( error) ( interface{}) {
	defer func() {
		if  := recover();  != nil {
			if  := reflect.ValueOf(); .Kind() == reflect.Ptr && .IsNil() {
				 = nil
			} else {
				 = fmt.Sprintf("PANIC in Error method: %v", )
			}
		}
	}()
	 = .Error()
	return
}