package smithy

import (
	
	
	
)

// An InvalidParamsError provides wrapping of invalid parameter errors found when
// validating API operation input parameters.
type InvalidParamsError struct {
	// Context is the base context of the invalid parameter group.
	Context string
	errs    []InvalidParamError
}

// Add adds a new invalid parameter error to the collection of invalid
// parameters. The context of the invalid parameter will be updated to reflect
// this collection.
func ( *InvalidParamsError) ( InvalidParamError) {
	.SetContext(.Context)
	.errs = append(.errs, )
}

// AddNested adds the invalid parameter errors from another InvalidParamsError
// value into this collection. The nested errors will have their nested context
// updated and base context to reflect the merging.
//
// Use for nested validations errors.
func ( *InvalidParamsError) ( string,  InvalidParamsError) {
	for ,  := range .errs {
		.SetContext(.Context)
		.AddNestedContext()
		.errs = append(.errs, )
	}
}

// Len returns the number of invalid parameter errors
func ( *InvalidParamsError) () int {
	return len(.errs)
}

// Error returns the string formatted form of the invalid parameters.
func ( InvalidParamsError) () string {
	 := &bytes.Buffer{}
	fmt.Fprintf(, "%d validation error(s) found.\n", len(.errs))

	for ,  := range .errs {
		fmt.Fprintf(, "- %s\n", .Error())
	}

	return .String()
}

// Errs returns a slice of the invalid parameters
func ( InvalidParamsError) () []error {
	 := make([]error, len(.errs))
	for  := 0;  < len(); ++ {
		[] = .errs[]
	}

	return 
}

// An InvalidParamError represents an invalid parameter error type.
type InvalidParamError interface {
	error

	// Field name the error occurred on.
	Field() string

	// SetContext updates the context of the error.
	SetContext(string)

	// AddNestedContext updates the error's context to include a nested level.
	AddNestedContext(string)
}

type invalidParamError struct {
	context       string
	nestedContext string
	field         string
	reason        string
}

// Error returns the string version of the invalid parameter error.
func ( invalidParamError) () string {
	return fmt.Sprintf("%s, %s.", .reason, .Field())
}

// Field Returns the field and context the error occurred.
func ( invalidParamError) () string {
	 := &strings.Builder{}
	.WriteString(.context)
	if .Len() > 0 {
		if len(.nestedContext) == 0 || (len(.nestedContext) > 0 && .nestedContext[:1] != "[") {
			.WriteRune('.')
		}
	}
	if len(.nestedContext) > 0 {
		.WriteString(.nestedContext)
		.WriteRune('.')
	}
	.WriteString(.field)
	return .String()
}

// SetContext updates the base context of the error.
func ( *invalidParamError) ( string) {
	.context = 
}

// AddNestedContext prepends a context to the field's path.
func ( *invalidParamError) ( string) {
	if len(.nestedContext) == 0 {
		.nestedContext = 
		return
	}
	// Check if our nested context is an index into a slice or map
	if .nestedContext[:1] != "[" {
		.nestedContext = fmt.Sprintf("%s.%s", , .nestedContext)
		return
	}
	.nestedContext =  + .nestedContext
}

// An ParamRequiredError represents an required parameter error.
type ParamRequiredError struct {
	invalidParamError
}

// NewErrParamRequired creates a new required parameter error.
func ( string) *ParamRequiredError {
	return &ParamRequiredError{
		invalidParamError{
			field:  ,
			reason: fmt.Sprintf("missing required field"),
		},
	}
}