/*
 * 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 configurator

import (
	"strings"
)

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

import (
	"github.com/apache/dubbo-go/common"
	"github.com/apache/dubbo-go/common/constant"
	"github.com/apache/dubbo-go/common/extension"
	"github.com/apache/dubbo-go/config_center"
)

func init() {
	extension.SetDefaultConfigurator(newConfigurator)
}

func newConfigurator(url *common.URL) config_center.Configurator {
	return &overrideConfigurator{configuratorUrl: url}
}

type overrideConfigurator struct {
	configuratorUrl *common.URL
}

func (c *overrideConfigurator) GetUrl() *common.URL {
	return c.configuratorUrl
}

func (c *overrideConfigurator) Configure(url *common.URL) {
	// remove configuratorUrl some param that can not be configured
	if c.configuratorUrl.GetParam(constant.ENABLED_KEY, "true") == "false" || len(c.configuratorUrl.Location) == 0 {
		return
	}

	// branch for version 2.7.x
	apiVersion := c.configuratorUrl.GetParam(constant.CONFIG_VERSION_KEY, "")
	if len(apiVersion) != 0 {
		currentSide := url.GetParam(constant.SIDE_KEY, "")
		configuratorSide := c.configuratorUrl.GetParam(constant.SIDE_KEY, "")
		if currentSide == configuratorSide && common.DubboRole[common.CONSUMER] == currentSide && c.configuratorUrl.Port == "0" {
			localIP, _ := gxnet.GetLocalIP()
			c.configureIfMatch(localIP, url)
		} else if currentSide == configuratorSide && common.DubboRole[common.PROVIDER] == currentSide && c.configuratorUrl.Port == url.Port {
			c.configureIfMatch(url.Ip, url)
		}
	} else {
		// branch for version 2.6.x and less
		c.configureDeprecated(url)
	}
}

func (c *overrideConfigurator) configureIfMatchInternal(url *common.URL) {
	configApp := c.configuratorUrl.GetParam(constant.APPLICATION_KEY, c.configuratorUrl.Username)
	currentApp := url.GetParam(constant.APPLICATION_KEY, url.Username)
	if len(configApp) == 0 || constant.ANY_VALUE == configApp || configApp == currentApp {
		conditionKeys := gxset.NewSet()
		conditionKeys.Add(constant.CATEGORY_KEY)
		conditionKeys.Add(constant.CHECK_KEY)
		conditionKeys.Add(constant.ENABLED_KEY)
		conditionKeys.Add(constant.GROUP_KEY)
		conditionKeys.Add(constant.VERSION_KEY)
		conditionKeys.Add(constant.APPLICATION_KEY)
		conditionKeys.Add(constant.SIDE_KEY)
		conditionKeys.Add(constant.CONFIG_VERSION_KEY)
		conditionKeys.Add(constant.COMPATIBLE_CONFIG_KEY)
		returnUrl := false
		c.configuratorUrl.RangeParams(func(k, _ string) bool {
			value := c.configuratorUrl.GetParam(k, "")
			if strings.HasPrefix(k, "~") || k == constant.APPLICATION_KEY || k == constant.SIDE_KEY {
				conditionKeys.Add(k)
				if len(value) != 0 && value != constant.ANY_VALUE && value != url.GetParam(strings.TrimPrefix(k, "~"), "") {
					returnUrl = true
					return false
				}
			}
			return true
		})
		if returnUrl {
			return
		}
		configUrl := c.configuratorUrl.CloneExceptParams(conditionKeys)
		url.SetParams(configUrl.GetParams())
	}
}

// configureIfMatch translate from java, compatible rules in java
func (c *overrideConfigurator) configureIfMatch(host string, url *common.URL) {
	if constant.ANYHOST_VALUE == c.configuratorUrl.Ip || host == c.configuratorUrl.Ip {
		providers := c.configuratorUrl.GetParam(constant.OVERRIDE_PROVIDERS_KEY, "")
		if len(providers) == 0 || strings.Contains(providers, url.Location) || strings.Contains(providers, constant.ANYHOST_VALUE) {
			c.configureIfMatchInternal(url)
		}
	}
}

func (c *overrideConfigurator) configureDeprecated(url *common.URL) {
	// If override url has port, means it is a provider address. We want to control a specific provider with this override url, it may take effect on the specific provider instance or on consumers holding this provider instance.
	if c.configuratorUrl.Port != "0" {
		if url.Port == c.configuratorUrl.Port {
			c.configureIfMatch(url.Ip, url)
		}
	} else {
		// override url don't have a port, means the ip override url specify is a consumer address or 0.0.0.0
		// 1.If it is a consumer ip address, the intention is to control a specific consumer instance, it must takes effect at the consumer side, any provider received this override url should ignore;
		// 2.If the ip is 0.0.0.0, this override url can be used on consumer, and also can be used on provider
		if url.GetParam(constant.SIDE_KEY, "") == common.DubboRole[common.CONSUMER] {
			localIP, _ := gxnet.GetLocalIP()
			c.configureIfMatch(localIP, url)
		} else {
			c.configureIfMatch(constant.ANYHOST_VALUE, url)
		}
	}
}
