package s3shared

import (
	
	
	
	
	
)

// ErrorComponents represents the error response fields
// that will be deserialized from an xml error response body
type ErrorComponents struct {
	Code      string `xml:"Code"`
	Message   string `xml:"Message"`
	RequestID string `xml:"RequestId"`
	HostID    string `xml:"HostId"`
}

// GetUnwrappedErrorResponseComponents returns the error fields from an xml error response body
func ( io.Reader) (ErrorComponents, error) {
	var  ErrorComponents
	if  := xml.NewDecoder().Decode(&);  != nil &&  != io.EOF {
		return ErrorComponents{}, fmt.Errorf("error while deserializing xml error response : %w", )
	}
	return , nil
}

// GetWrappedErrorResponseComponents returns the error fields from an xml error response body
// in which error code, and message are wrapped by a <Error> tag
func ( io.Reader) (ErrorComponents, error) {
	var  struct {
		      string `xml:"Error>Code"`
		   string `xml:"Error>Message"`
		 string `xml:"RequestId"`
		    string `xml:"HostId"`
	}

	if  := xml.NewDecoder().Decode(&);  != nil &&  != io.EOF {
		return ErrorComponents{}, fmt.Errorf("error while deserializing xml error response : %w", )
	}

	return ErrorComponents{
		Code:      .,
		Message:   .,
		RequestID: .,
		HostID:    .,
	}, nil
}

// GetErrorResponseComponents retrieves error components according to passed in options
func ( io.Reader,  ErrorResponseDeserializerOptions) (ErrorComponents, error) {
	var  ErrorComponents
	var  error

	if .IsWrappedWithErrorTag {
		,  = GetWrappedErrorResponseComponents()
	} else {
		,  = GetUnwrappedErrorResponseComponents()
	}

	if  != nil {
		return ErrorComponents{}, 
	}

	// If an error code or message is not retrieved, it is derived from the http status code
	// eg, for S3 service, we derive err code and message, if none is found
	if .UseStatusCode && len(.Code) == 0 &&
		len(.Message) == 0 {
		// derive code and message from status code
		 := http.StatusText(.StatusCode)
		.Code = strings.Replace(, " ", "", -1)
		.Message = 
	}
	return , nil
}

// ErrorResponseDeserializerOptions represents error response deserializer options for s3 and s3-control service
type ErrorResponseDeserializerOptions struct {
	// UseStatusCode denotes if status code should be used to retrieve error code, msg
	UseStatusCode bool

	// StatusCode is status code of error response
	StatusCode int

	//IsWrappedWithErrorTag represents if error response's code, msg is wrapped within an
	// additional <Error> tag
	IsWrappedWithErrorTag bool
}