/*
 * Copyright 2023 CloudWeGo Authors
 *
 * 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 generic

import (
	"github.com/cloudwego/dynamicgo/conv"

	"github.com/cloudwego/kitex/pkg/generic/thrift"
)

var (
	DefaultHTTPDynamicGoConvOpts = conv.Options{
		EnableHttpMapping:      true,
		EnableValueMapping:     true,
		WriteRequireField:      true,
		WriteDefaultField:      true,
		OmitHttpMappingErrors:  true,
		NoBase64Binary:         true,
		UseKitexHttpEncoding:   true,
		WriteHttpValueFallback: true,
		ReadHttpValueFallback:  true,
		MergeBaseFunc:          thrift.MergeBase,
	}
	DefaultJSONDynamicGoConvOpts = conv.Options{
		WriteRequireField:  true,
		WriteDefaultField:  true,
		EnableValueMapping: true,
		String2Int64:       true,
		MergeBaseFunc:      thrift.MergeBase,
	}
)

type Options struct {
	// options for dynamicgo conversion
	dynamicgoConvOpts conv.Options
	// flag to set whether to store http resp body into HTTPResponse.RawBody
	useRawBodyForHTTPResp bool
}

type Option struct {
	F func(opt *Options)
}

// apply applies all options
func (o *Options) apply(opts []Option) {
	for _, op := range opts {
		op.F(o)
	}
}

// WithCustomDynamicGoConvOpts sets custom conv.Options
func WithCustomDynamicGoConvOpts(opts *conv.Options) Option {
	return Option{F: func(opt *Options) {
		opt.dynamicgoConvOpts = *opts
	}}
}

// UseRawBodyForHTTPResp sets whether to set body of response for http generic call into HTTPResponse.RawBody or not.
// if this is disabled, the body will be stored only into HTTPResponse.Body
func UseRawBodyForHTTPResp(enable bool) Option {
	return Option{F: func(opt *Options) {
		opt.useRawBodyForHTTPResp = enable
	}}
}
