package cmp

import (
	
	
	
	
	

	
)

// A Result of a Comparison.
type Result interface {
	Success() bool
}

// StringResult is an implementation of Result that reports the error message
// string verbatim and does not provide any templating or formatting of the
// message.
type StringResult struct {
	success bool
	message string
}

// Success returns true if the comparison was successful.
func ( StringResult) () bool {
	return .success
}

// FailureMessage returns the message used to provide additional information
// about the failure.
func ( StringResult) () string {
	return .message
}

// ResultSuccess is a constant which is returned by a ComparisonWithResult to
// indicate success.
var ResultSuccess = StringResult{success: true}

// ResultFailure returns a failed Result with a failure message.
func ( string) StringResult {
	return StringResult{message: }
}

// ResultFromError returns ResultSuccess if err is nil. Otherwise ResultFailure
// is returned with the error message as the failure message.
func ( error) Result {
	if  == nil {
		return ResultSuccess
	}
	return ResultFailure(.Error())
}

type templatedResult struct {
	template string
	data     map[string]interface{}
}

func ( templatedResult) () bool {
	return false
}

func ( templatedResult) ( []ast.Expr) string {
	,  := renderMessage(, )
	if  != nil {
		return fmt.Sprintf("failed to render failure message: %s", )
	}
	return 
}

func ( templatedResult) ( int) error {
	// TODO: would be nice to have structured data instead of a map
	return source.UpdateExpectedValue(+1, .data["x"], .data["y"])
}

// ResultFailureTemplate returns a Result with a template string and data which
// can be used to format a failure message. The template may access data from .Data,
// the comparison args with the callArg function, and the formatNode function may
// be used to format the call args.
func ( string,  map[string]interface{}) Result {
	return templatedResult{template: , data: }
}

func ( templatedResult,  []ast.Expr) (string, error) {
	 := template.New("failure").Funcs(template.FuncMap{
		"formatNode": source.FormatNode,
		"callArg": func( int) ast.Expr {
			if  >= len() {
				return nil
			}
			return []
		},
		// TODO: any way to include this from ErrorIS instead of here?
		"notStdlibErrorType": func( interface{}) bool {
			 := reflect.TypeOf()
			return  != stdlibFmtErrorType &&  != stdlibErrorNewType
		},
	})
	var  error
	,  = .Parse(.template)
	if  != nil {
		return "", 
	}
	 := new(bytes.Buffer)
	 = .Execute(, map[string]interface{}{
		"Data": .data,
	})
	return .String(), 
}