/*
 * 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 (
	"sync"
)

import (
	gxset "github.com/dubbogo/gost/container/set"

	"gopkg.in/yaml.v2"
)

import (
	"dubbo.apache.org/dubbo-go/v3/common"
	"dubbo.apache.org/dubbo-go/v3/common/constant"
	"dubbo.apache.org/dubbo-go/v3/config_center/parser"
	"dubbo.apache.org/dubbo-go/v3/remoting"
)

// MockDynamicConfigurationFactory defines content
type MockDynamicConfigurationFactory struct {
	Content string
}

const (
	mockServiceName = "org.apache.dubbo-go.mockService"
)

var (
	once                 sync.Once
	dynamicConfiguration *MockDynamicConfiguration
)

// GetDynamicConfiguration returns a DynamicConfiguration
func (f *MockDynamicConfigurationFactory) GetDynamicConfiguration(_ *common.URL) (DynamicConfiguration, error) {
	var err error
	once.Do(func() {
		dynamicConfiguration = &MockDynamicConfiguration{listener: map[string]ConfigurationListener{}}
		dynamicConfiguration.SetParser(&parser.DefaultConfigurationParser{})

		dynamicConfiguration.content = `
	dubbo.consumer.request_timeout=5s
	dubbo.consumer.connect_timeout=5s
	dubbo.application.organization=ikurento.com
	dubbo.application.name=BDTService
	dubbo.application.module=dubbogo user-info server
	dubbo.application.version=0.0.1
	dubbo.application.owner=ZX
	dubbo.application.environment=dev
	dubbo.registries.hangzhouzk.protocol=zookeeper
	dubbo.registries.hangzhouzk.timeout=3s
	dubbo.registries.hangzhouzk.address=127.0.0.1:2181
	dubbo.registries.shanghaizk.protocol=zookeeper
	dubbo.registries.shanghaizk.timeout=3s
	dubbo.registries.shanghaizk.address=127.0.0.1:2182
	dubbo.service.com.ikurento.user.UserProvider.protocol=dubbo
	dubbo.service.com.ikurento.user.UserProvider.interface=com.ikurento.user.UserProvider
	dubbo.service.com.ikurento.user.UserProvider.loadbalance=random
	dubbo.service.com.ikurento.user.UserProvider.warmup=100
	dubbo.service.com.ikurento.user.UserProvider.cluster=failover
	dubbo.protocols.jsonrpc1.name=jsonrpc
	dubbo.protocols.jsonrpc1.ip=127.0.0.1
	dubbo.protocols.jsonrpc1.port=20001
`
	})
	if len(f.Content) != 0 {
		dynamicConfiguration.content = f.Content
	}
	return dynamicConfiguration, err
}

// PublishConfig will publish the config with the (key, group, value) pair
func (c *MockDynamicConfiguration) PublishConfig(string, string, string) error {
	return nil
}

// GetConfigKeysByGroup will return all keys with the group
func (c *MockDynamicConfiguration) GetConfigKeysByGroup(group string) (*gxset.HashSet, error) {
	return gxset.NewSet(c.content), nil
}

// MockDynamicConfiguration uses to parse content and defines listener
type MockDynamicConfiguration struct {
	BaseDynamicConfiguration
	parser   parser.ConfigurationParser
	content  string
	listener map[string]ConfigurationListener
}

// AddListener adds a listener for MockDynamicConfiguration
func (c *MockDynamicConfiguration) AddListener(key string, listener ConfigurationListener, _ ...Option) {
	c.listener[key] = listener
}

// RemoveListener removes the listener for MockDynamicConfiguration
func (c *MockDynamicConfiguration) RemoveListener(_ string, _ ConfigurationListener, _ ...Option) {
	// mock remove
}

// GetConfig returns content of MockDynamicConfiguration
func (c *MockDynamicConfiguration) GetConfig(_ string, _ ...Option) (string, error) {
	return c.content, nil
}

// GetConfigs For zookeeper, getConfig and getConfigs have the same meaning.
func (c *MockDynamicConfiguration) GetConfigs(key string, opts ...Option) (string, error) {
	return c.GetConfig(key, opts...)
}

// Parser returns a parser of MockDynamicConfiguration
func (c *MockDynamicConfiguration) Parser() parser.ConfigurationParser {
	return c.parser
}

// SetParser sets parser of MockDynamicConfiguration
func (c *MockDynamicConfiguration) SetParser(p parser.ConfigurationParser) {
	c.parser = p
}

// GetProperties gets content of MockDynamicConfiguration
func (c *MockDynamicConfiguration) GetProperties(_ string, _ ...Option) (string, error) {
	return c.content, nil
}

// GetInternalProperty For zookeeper, getConfig and getConfigs have the same meaning.
func (c *MockDynamicConfiguration) GetInternalProperty(key string, opts ...Option) (string, error) {
	return c.GetProperties(key, opts...)
}

// GetRule gets properties of MockDynamicConfiguration
func (c *MockDynamicConfiguration) GetRule(key string, opts ...Option) (string, error) {
	return c.GetProperties(key, opts...)
}

// MockServiceConfigEvent returns ConfiguratorConfig
func (c *MockDynamicConfiguration) MockServiceConfigEvent() {
	config := &parser.ConfiguratorConfig{
		ConfigVersion: "2.7.1",
		Scope:         parser.GeneralType,
		Key:           mockServiceName,
		Enabled:       true,
		Configs: []parser.ConfigItem{
			{
				Type:       parser.GeneralType,
				Enabled:    true,
				Addresses:  []string{"0.0.0.0"},
				Services:   []string{mockServiceName},
				Side:       "provider",
				Parameters: map[string]string{"cluster": "mock1"},
			},
		},
	}
	value, _ := yaml.Marshal(config)
	key := "group*" + mockServiceName + ":1.0.0" + constant.ConfiguratorSuffix
	c.listener[key].Process(&ConfigChangeEvent{Key: key, Value: string(value), ConfigType: remoting.EventTypeAdd})
}

// MockApplicationConfigEvent returns ConfiguratorConfig
func (c *MockDynamicConfiguration) MockApplicationConfigEvent() {
	config := &parser.ConfiguratorConfig{
		ConfigVersion: "2.7.1",
		Scope:         parser.ScopeApplication,
		Key:           mockServiceName,
		Enabled:       true,
		Configs: []parser.ConfigItem{
			{
				Type:       parser.ScopeApplication,
				Enabled:    true,
				Addresses:  []string{"0.0.0.0"},
				Services:   []string{mockServiceName},
				Side:       "provider",
				Parameters: map[string]string{"cluster": "mock1"},
			},
		},
	}
	value, _ := yaml.Marshal(config)
	key := "test-application" + constant.ConfiguratorSuffix
	c.listener[key].Process(&ConfigChangeEvent{Key: key, Value: string(value), ConfigType: remoting.EventTypeAdd})
}
