/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 config_center

import (
	"strconv"
	"strings"
	"time"
)

import (
	"dubbo.apache.org/dubbo-go/v3/common/constant"
	"dubbo.apache.org/dubbo-go/v3/common/constant/file"
	"dubbo.apache.org/dubbo-go/v3/global"
)

type Options struct {
	Center *global.CenterConfig
}

func defaultOptions() *Options {
	return &Options{Center: global.DefaultCenterConfig()}
}

func NewOptions(opts ...Option) *Options {
	centerOptions := defaultOptions()
	for _, opt := range opts {
		opt(centerOptions)
	}
	return centerOptions
}

type Option func(*Options)

func WithZookeeper() Option {
	return func(opts *Options) {
		opts.Center.Protocol = constant.ZookeeperKey
	}
}

func WithNacos() Option {
	return func(opts *Options) {
		opts.Center.Protocol = constant.NacosKey
	}
}

func WithAddress(address string) Option {
	return func(opts *Options) {
		if i := strings.Index(address, "://"); i > 0 {
			opts.Center.Protocol = address[0:i]
		}
		opts.Center.Address = address
	}
}

func WithDataID(id string) Option {
	return func(opts *Options) {
		opts.Center.DataId = id
	}
}

func WithCluster(cluster string) Option {
	return func(opts *Options) {
		opts.Center.Cluster = cluster
	}
}

func WithGroup(group string) Option {
	return func(opts *Options) {
		opts.Center.Group = group
	}
}

func WithUsername(username string) Option {
	return func(opts *Options) {
		opts.Center.Username = username
	}
}

func WithPassword(password string) Option {
	return func(opts *Options) {
		opts.Center.Password = password
	}
}

func WithNamespace(namespace string) Option {
	return func(opts *Options) {
		opts.Center.Namespace = namespace
	}
}

func WithAppID(id string) Option {
	return func(opts *Options) {
		opts.Center.AppID = id
	}
}

func WithTimeout(timeout time.Duration) Option {
	return func(opts *Options) {
		opts.Center.Timeout = strconv.Itoa(int(timeout.Milliseconds()))
	}
}

func WithParams(params map[string]string) Option {
	return func(opts *Options) {
		opts.Center.Params = params
	}
}

func WithFile() Option {
	return func(opts *Options) {
		opts.Center.Protocol = constant.FileKey
	}
}

func WithFileExtJson() Option {
	return func(opts *Options) {
		opts.Center.FileExtension = string(file.JSON)
	}
}

func WithFileExtToml() Option {
	return func(opts *Options) {
		opts.Center.FileExtension = string(file.TOML)
	}
}

func WithFileExtYaml() Option {
	return func(opts *Options) {
		opts.Center.FileExtension = string(file.YAML)
	}
}

func WithFileExtYml() Option {
	return func(opts *Options) {
		opts.Center.FileExtension = string(file.YML)
	}
}

func WithFileExtProperties() Option {
	return func(opts *Options) {
		opts.Center.FileExtension = string(file.PROPERTIES)
	}
}
