/*
 * Copyright 1999-2020 Alibaba Group Holding Ltd.
 *
 * 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 constant

import (
	"os"
	"time"

	"github.com/nacos-group/nacos-sdk-go/v2/common/file"
)

func NewClientConfig(opts ...ClientOption) *ClientConfig {
	clientConfig := &ClientConfig{
		TimeoutMs:            10 * 1000,
		BeatInterval:         5 * 1000,
		OpenKMS:              false,
		CacheDir:             file.GetCurrentPath() + string(os.PathSeparator) + "cache",
		UpdateThreadNum:      20,
		NotLoadCacheAtStart:  false,
		UpdateCacheWhenEmpty: false,
		LogDir:               file.GetCurrentPath() + string(os.PathSeparator) + "log",
		LogLevel:             "info",
	}

	for _, opt := range opts {
		opt(clientConfig)
	}

	return clientConfig
}

// ClientOption ...
type ClientOption func(*ClientConfig)

// WithTimeoutMs ...
func WithTimeoutMs(timeoutMs uint64) ClientOption {
	return func(config *ClientConfig) {
		config.TimeoutMs = timeoutMs
	}
}

// WithAppName ...
func WithAppName(appName string) ClientOption {
	return func(config *ClientConfig) {
		config.AppName = appName
	}
}

// WithBeatInterval ...
func WithBeatInterval(beatInterval int64) ClientOption {
	return func(config *ClientConfig) {
		config.BeatInterval = beatInterval
	}
}

// WithNamespaceId ...
func WithNamespaceId(namespaceId string) ClientOption {
	return func(config *ClientConfig) {
		config.NamespaceId = namespaceId
	}
}

// WithEndpoint ...
func WithEndpoint(endpoint string) ClientOption {
	return func(config *ClientConfig) {
		config.Endpoint = endpoint
	}
}

// WithEndpointContextPath ...
func WithEndpointContextPath(endpointContextPath string) ClientOption {
	return func(config *ClientConfig) {
		config.EndpointContextPath = endpointContextPath
	}
}

// WithEndpointQueryParams ...
func WithEndpointQueryParams(endpointQueryPrams string) ClientOption {
	return func(config *ClientConfig) {
		config.EndpointQueryParams = endpointQueryPrams
	}
}

// WithClusterName ...
func WithClusterName(clusterName string) ClientOption {
	return func(config *ClientConfig) {
		config.ClusterName = clusterName
	}
}

// WithRegionId ...
func WithRegionId(regionId string) ClientOption {
	return func(config *ClientConfig) {
		config.RegionId = regionId
	}
}

// WithAccessKey ...
func WithAccessKey(accessKey string) ClientOption {
	return func(config *ClientConfig) {
		config.AccessKey = accessKey
	}
}

// WithSecretKey ...
func WithSecretKey(secretKey string) ClientOption {
	return func(config *ClientConfig) {
		config.SecretKey = secretKey
	}
}

// WithOpenKMS ...
func WithOpenKMS(openKMS bool) ClientOption {
	return func(config *ClientConfig) {
		config.OpenKMS = openKMS
	}
}

// WithOpenKMS ...
func WithKMSVersion(kmsVersion KMSVersion) ClientOption {
	return func(config *ClientConfig) {
		config.KMSVersion = kmsVersion
	}
}

func WithKMSv3Config(kmsv3Config *KMSv3Config) ClientOption {
	return func(config *ClientConfig) {
		config.KMSv3Config = kmsv3Config
	}
}

// WithCacheDir ...
func WithCacheDir(cacheDir string) ClientOption {
	return func(config *ClientConfig) {
		config.CacheDir = cacheDir
	}
}

// WithDisableUseSnapShot ...
func WithDisableUseSnapShot(disableUseSnapShot bool) ClientOption {
	return func(config *ClientConfig) {
		config.DisableUseSnapShot = disableUseSnapShot
	}
}

// WithUpdateThreadNum ...
func WithUpdateThreadNum(updateThreadNum int) ClientOption {
	return func(config *ClientConfig) {
		config.UpdateThreadNum = updateThreadNum
	}
}

// WithNotLoadCacheAtStart ...
func WithNotLoadCacheAtStart(notLoadCacheAtStart bool) ClientOption {
	return func(config *ClientConfig) {
		config.NotLoadCacheAtStart = notLoadCacheAtStart
	}
}

// WithUpdateCacheWhenEmpty ...
func WithUpdateCacheWhenEmpty(updateCacheWhenEmpty bool) ClientOption {
	return func(config *ClientConfig) {
		config.UpdateCacheWhenEmpty = updateCacheWhenEmpty
	}
}

// WithUsername ...
func WithUsername(username string) ClientOption {
	return func(config *ClientConfig) {
		config.Username = username
	}
}

// WithPassword ...
func WithPassword(password string) ClientOption {
	return func(config *ClientConfig) {
		config.Password = password
	}
}

// WithLogDir ...
func WithLogDir(logDir string) ClientOption {
	return func(config *ClientConfig) {
		config.LogDir = logDir
	}
}

// WithLogLevel ...
func WithLogLevel(logLevel string) ClientOption {
	return func(config *ClientConfig) {
		config.LogLevel = logLevel
	}
}

// WithLogSampling ...
func WithLogSampling(tick time.Duration, initial int, thereafter int) ClientOption {
	return func(config *ClientConfig) {
		config.LogSampling = &ClientLogSamplingConfig{initial, thereafter, tick}
	}
}

// WithLogRollingConfig ...
func WithLogRollingConfig(rollingConfig *ClientLogRollingConfig) ClientOption {
	return func(config *ClientConfig) {
		config.LogRollingConfig = rollingConfig
	}
}

func WithTLS(tlsCfg TLSConfig) ClientOption {
	return func(config *ClientConfig) {
		config.TLSCfg = tlsCfg
	}
}
